Analyzing Factors Influencing Heart Disease Severity using Multiple Linear Regression


Data Science Visualization

Project Overview:

This project aims to analyze the factors influencing the severity of heart disease using multiple linear regression. The goal is to understand how various health indicators contribute to the severity of heart disease, measured on a continuous scale.



Dataset Selection

Source: Kaggle - Heart Failure Prediction Dataset

Description: This dataset contains 12 variables including age, sex, chest pain type, resting blood pressure, serum cholesterol, fasting blood sugar, resting electrocardiographic results, maximum heart rate achieved, exercise-induced angina, oldpeak (ST depression induced by exercise relative to rest), slope of the peak exercise ST segment, and the number of major vessels colored by fluoroscopy. The target variable is the presence or absence of heart disease. This dataset aligns with the project guideline’s requirements of having at least 10 variables and 100 observational rows, with both quantitative and categorical variables.

Datasets Name: hearts

Website to Download the Data: Kaggle - Heart Failure Prediction Dataset URL : https://www.kaggle.com/datasets/fedesoriano/heart-failure-prediction

Datasets Description

  • Cardiovascular diseases (CVDs) are the number 1 cause of death globally, taking an estimated 17.9 million lives each year, which accounts for 31% of all deaths worldwide. Four out of 5CVD deaths are due to heart attacks and strokes, and one-third of these deaths occur prematurely in people under 70 years of age. Heart failure is a common event caused by CVDs and this dataset contains 11 features that can be used to predict a possible heart disease.

  • People with cardiovascular disease or who are at high cardiovascular risk (due to the presence of one or more risk factors such as hypertension, diabetes, hyperlipidaemia or already established disease) need early detection and management wherein a machine learning model can be of great help.

Attribute Information

  • Age: age of the patient [years]
  • Sex: sex of the patient [M: Male, F: Female]
  • ChestPainType: chest pain type [TA: Typical Angina, ATA: Atypical Angina, NAP: Non-Anginal Pain, ASY: Asymptomatic]
  • RestingBP: resting blood pressure [mm Hg]
  • Cholesterol: serum cholesterol [mm/dl]
  • FastingBS: fasting blood sugar [1: if FastingBS > 120 mg/dl, 0: otherwise]
  • RestingECG: resting electrocardiogram results [Normal: Normal, ST: having ST-T wave abnormality (T wave inversions and/or ST elevation or depression of > 0.05 mV), LVH: showing probable or definite left ventricular hypertrophy by Estes’ criteria]
  • MaxHR: maximum heart rate achieved [Numeric value between 60 and 202]
  • ExerciseAngina: exercise-induced angina [Y: Yes, N: No]
  • Oldpeak: oldpeak = ST [Numeric value measured in depression]
  • ST_Slope: the slope of the peak exercise ST segment [Up: upsloping, Flat: flat, Down: downsloping]
  • HeartDisease: output class [1: heart disease, 0: Normal] ***


Research Questions

  1. Which health indicators are the most significant predictors of heart disease severity?
  2. How do categorical variables such as sex and chest pain type influence the prediction of heart disease?
  3. What is the relationship between quantitative variables like cholesterol levels, resting blood pressure, and maximum heart rate with the severity of heart disease?

Expected Outcomes

The project aims to identify key predictors of heart disease severity and provide a comprehensive analysis that can aid in early detection and better management of cardiovascular diseases. By leveraging statistical and machine learning techniques, the findings will contribute to the understanding of heart disease risk factors and support the development of preventive measures



Data Import and Conversion

Purpose

Data Import: To load the dataset into R for analysis. Check for Missing Values: To ensure data completeness and integrity. Data Conversion: To ensure categorical variables are treated appropriately in the analysis.

## # A tibble: 6 × 12
##     Age Sex   ChestPainType RestingBP Cholesterol FastingBS RestingECG MaxHR
##   <dbl> <chr> <chr>             <dbl>       <dbl>     <dbl> <chr>      <dbl>
## 1    40 M     ATA                 140         289         0 Normal       172
## 2    49 F     NAP                 160         180         0 Normal       156
## 3    37 M     ATA                 130         283         0 ST            98
## 4    48 F     ASY                 138         214         0 Normal       108
## 5    54 M     NAP                 150         195         0 Normal       122
## 6    39 M     NAP                 120         339         0 Normal       170
## # ℹ 4 more variables: ExerciseAngina <chr>, Oldpeak <dbl>, ST_Slope <chr>,
## #   HeartDisease <dbl>
##       Age            Sex            ChestPainType        RestingBP    
##  Min.   :28.00   Length:918         Length:918         Min.   :  0.0  
##  1st Qu.:47.00   Class :character   Class :character   1st Qu.:120.0  
##  Median :54.00   Mode  :character   Mode  :character   Median :130.0  
##  Mean   :53.51                                         Mean   :132.4  
##  3rd Qu.:60.00                                         3rd Qu.:140.0  
##  Max.   :77.00                                         Max.   :200.0  
##   Cholesterol      FastingBS       RestingECG            MaxHR      
##  Min.   :  0.0   Min.   :0.0000   Length:918         Min.   : 60.0  
##  1st Qu.:173.2   1st Qu.:0.0000   Class :character   1st Qu.:120.0  
##  Median :223.0   Median :0.0000   Mode  :character   Median :138.0  
##  Mean   :198.8   Mean   :0.2331                      Mean   :136.8  
##  3rd Qu.:267.0   3rd Qu.:0.0000                      3rd Qu.:156.0  
##  Max.   :603.0   Max.   :1.0000                      Max.   :202.0  
##  ExerciseAngina        Oldpeak          ST_Slope          HeartDisease   
##  Length:918         Min.   :-2.6000   Length:918         Min.   :0.0000  
##  Class :character   1st Qu.: 0.0000   Class :character   1st Qu.:0.0000  
##  Mode  :character   Median : 0.6000   Mode  :character   Median :1.0000  
##                     Mean   : 0.8874                      Mean   :0.5534  
##                     3rd Qu.: 1.5000                      3rd Qu.:1.0000  
##                     Max.   : 6.2000                      Max.   :1.0000

Data Tibble.

## [1] TRUE

Tidy Data

## [1] 0

To identify and characterize the dataset thoroughly, we can utilize several R functions that provide detailed insights into the structure, summary statistics, distribution, and relationships between the variables

Understanding the Data Structure

## spc_tbl_ [918 × 12] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ Age           : num [1:918] 40 49 37 48 54 39 45 54 37 48 ...
##  $ Sex           : chr [1:918] "M" "F" "M" "F" ...
##  $ ChestPainType : chr [1:918] "ATA" "NAP" "ATA" "ASY" ...
##  $ RestingBP     : num [1:918] 140 160 130 138 150 120 130 110 140 120 ...
##  $ Cholesterol   : num [1:918] 289 180 283 214 195 339 237 208 207 284 ...
##  $ FastingBS     : num [1:918] 0 0 0 0 0 0 0 0 0 0 ...
##  $ RestingECG    : chr [1:918] "Normal" "Normal" "ST" "Normal" ...
##  $ MaxHR         : num [1:918] 172 156 98 108 122 170 170 142 130 120 ...
##  $ ExerciseAngina: chr [1:918] "N" "N" "N" "Y" ...
##  $ Oldpeak       : num [1:918] 0 1 0 1.5 0 0 0 0 1.5 0 ...
##  $ ST_Slope      : chr [1:918] "Up" "Flat" "Up" "Flat" ...
##  $ HeartDisease  : num [1:918] 0 1 0 1 0 0 0 0 1 0 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   Age = col_double(),
##   ..   Sex = col_character(),
##   ..   ChestPainType = col_character(),
##   ..   RestingBP = col_double(),
##   ..   Cholesterol = col_double(),
##   ..   FastingBS = col_double(),
##   ..   RestingECG = col_character(),
##   ..   MaxHR = col_double(),
##   ..   ExerciseAngina = col_character(),
##   ..   Oldpeak = col_double(),
##   ..   ST_Slope = col_character(),
##   ..   HeartDisease = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>

Data Preprocessing

Convert categorical variables to dummy variables

## # A tibble: 918 × 12
##     SexF  SexM ChestPainTypeATA ChestPainTypeNAP ChestPainTypeTA FastingBS1
##    <dbl> <dbl>            <dbl>            <dbl>           <dbl>      <dbl>
##  1     0     1                1                0               0          0
##  2     1     0                0                1               0          0
##  3     0     1                1                0               0          0
##  4     1     0                0                0               0          0
##  5     0     1                0                1               0          0
##  6     0     1                0                1               0          0
##  7     1     0                1                0               0          0
##  8     0     1                1                0               0          0
##  9     0     1                0                0               0          0
## 10     1     0                1                0               0          0
## # ℹ 908 more rows
## # ℹ 6 more variables: RestingECGNormal <dbl>, RestingECGST <dbl>,
## #   ExerciseAnginaY <dbl>, ST_SlopeFlat <dbl>, ST_SlopeUp <dbl>,
## #   HeartDisease1 <dbl>


Categorical and Quantitative Variable Plots(EDA)

To generate insightful plots using ggplot2, we will create visualizations that highlight relationships and trends between categorical and quantitative variables in the heart disease dataset. These plots will include histograms, boxplots, and scatter plots with trend lines, which can help us uncover patterns and insights in the data.

Visualization Goals

Discription Distribution of Age by Heart Disease Status: Use histograms to show how age is distributed among those with and without heart disease. Boxplots of Cholesterol by Chest Pain Type: Compare cholesterol levels across different types of chest pain. Scatter Plot of Max Heart Rate vs. Age: Examine the relationship between age and maximum heart rate, differentiated by heart disease status. Bar Plot of Heart Disease by Sex: Show the proportion of heart disease across genders.

Distribution of Age by Heart Disease Status

Description and Interpretation

Age Distribution by Heart Disease Status

Description: This histogram shows the distribution of ages for individuals with and without heart disease. The blue bars represent individuals without heart disease (HeartDisease = 0), and the purple bars represent individuals with heart disease (HeartDisease = 1).

Interpretation:

Individuals with heart disease are generally older, with a noticeable increase in heart disease prevalence starting from the age of 40. The peak prevalence for individuals with heart disease is around 50 to 60 years. There are fewer young individuals (under 40) with heart disease, indicating age as a significant factor in heart disease prevalence.

Cholesterol Levels by Chest Pain Type

Description: This box plot shows the distribution of cholesterol levels for different chest pain types (ASY: Asymptomatic, ATA: Atypical Angina, NAP: Non-Anginal Pain, TA: Typical Angina).

Interpretation:

Individuals with asymptomatic (ASY) chest pain have a wider range of cholesterol levels, with many outliers indicating higher cholesterol. Those with typical angina (TA) and non-anginal pain (NAP) tend to have higher cholesterol levels compared to other chest pain types. Atypical angina (ATA) shows a more consistent range of cholesterol levels with fewer extreme values. Max Heart Rate vs. Age by Heart Disease Status

Description: This scatter plot shows the relationship between maximum heart rate and age, with different colors representing heart disease status (Red: No heart disease, Purple: Heart disease).

Interpretation:

There is a general decline in maximum heart rate with increasing age for both groups. Individuals without heart disease (red) tend to have higher maximum heart rates compared to those with heart disease (purple). This negative correlation suggests that as individuals age, their maximum heart rate decreases, and those with lower maximum heart rates are more likely to have heart disease.

Proportion of Heart Disease by Sex

Description: This bar plot shows the proportion of heart disease prevalence by sex. The pink bars represent individuals without heart disease (HeartDisease = 0), and the purple bars represent individuals with heart disease (HeartDisease = 1).

Interpretation:

Males (M) have a higher proportion of heart disease compared to females (F). The majority of females do not have heart disease, while a significant proportion of males do. This indicates that sex is an important factor, with males being more susceptible to heart disease. Overall Interpretation These visualizations provide important insights into the factors associated with heart disease:

Age: Older age groups have higher heart disease prevalence. Cholesterol: Higher cholesterol levels are more common in individuals with certain types of chest pain. Max Heart Rate: Lower maximum heart rates are associated with higher heart disease prevalence, especially in older individuals. Sex: Males are at a higher risk of developing heart disease compared to females.



Interactive Table



Interpretation of the Quantitative and Qualitative Plots

The visualizations reveal that older age groups (especially those over 40) have a higher prevalence of heart disease, with peak cases around 50-60 years. Cholesterol levels vary significantly with chest pain types, with asymptomatic individuals showing a wide range and higher levels, while typical angina and non-anginal pain are also associated with higher cholesterol. A declining maximum heart rate with age is observed, and those with heart disease generally have lower maximum heart rates. Additionally, males are at a higher risk of heart disease compared to females, highlighting the importance of age, cholesterol, maximum heart rate, and sex as critical factors in heart disease prevalence..



Correlation

To Visualize the Correlation Matrix, we Use a heatmap to visualize the correlations, highlighting both the strength and direction of relationships between variables.

Visualize the correlation matrix using corrplot

Interpretation of Correlation Matrix

This correlation matrix visualizes the relationships between different variables in the dataset. The color scale on the right indicates the strength and direction of the correlations, with values ranging from -1 to 1. Positive correlations are shown in shades of blue, while negative correlations are in shades of red.

Key Observations: Cholesterol:

Shows a weak positive correlation with MaxHR (0.24). Has a weak negative correlation with HeartDisease (-0.23), suggesting that higher cholesterol levels may slightly decrease the likelihood of heart disease. MaxHR:

Shows a moderate negative correlation with HeartDisease (-0.40), indicating that higher maximum heart rates are associated with a lower likelihood of heart disease. Has a weak negative correlation with Age (-0.38), meaning that older individuals tend to have lower maximum heart rates. FastingBS:

Shows a weak positive correlation with HeartDisease (0.27), suggesting that higher fasting blood sugar levels slightly increase the likelihood of heart disease. Has weak positive correlations with other variables like Age (0.20) and RestingBP (0.07). RestingBP:

Shows a weak positive correlation with HeartDisease (0.11), indicating a minor increase in heart disease likelihood with higher resting blood pressure. Has weak positive correlations with Age (0.25) and Oldpeak (0.16). Age:

Shows a weak positive correlation with HeartDisease (0.28), indicating that older age is associated with a higher likelihood of heart disease. Has weak to moderate positive correlations with other variables like RestingBP (0.25), Oldpeak (0.26), and FastingBS (0.20). Oldpeak:

Shows the strongest positive correlation with HeartDisease (0.40) among the variables, suggesting that higher ST depression is strongly associated with a higher likelihood of heart disease. Has weak positive correlations with other variables like Age (0.26) and RestingBP (0.16). Summary: MaxHR and Oldpeak are the most significant predictors of heart disease in this dataset, with MaxHR showing a moderate negative correlation and Oldpeak showing a moderate positive correlation with heart disease. Age and FastingBS also show weak positive correlations with heart disease, indicating that older age and higher fasting blood sugar levels are associated with a slightly higher likelihood of heart disease. Cholesterol and RestingBP show weaker correlations with heart disease, suggesting they are less influential predictors in this dataset. These correlations provide insights into the relationships between different health indicators and heart disease, helping to identify key factors that may contribute to the risk of heart disease.

Correlation Analysis Summary:


Regression Model

## 
## Call:
## lm(formula = HeartDisease ~ Age + Sex + RestingBP + Cholesterol + 
##     MaxHR + ExerciseAngina + Oldpeak + ST_Slope, data = heart_data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.0947 -0.1770  0.0085  0.1820  1.0592 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)      0.4287953  0.1479534   2.898  0.00384 ** 
## Age              0.0032174  0.0013784   2.334  0.01980 *  
## SexM             0.1855887  0.0292847   6.337 3.68e-10 ***
## RestingBP        0.0002044  0.0006501   0.314  0.75329    
## Cholesterol     -0.0006753  0.0001110  -6.082 1.75e-09 ***
## MaxHR           -0.0013184  0.0005426  -2.430  0.01530 *  
## ExerciseAnginaY  0.1916519  0.0281923   6.798 1.92e-11 ***
## Oldpeak          0.0592776  0.0131440   4.510 7.34e-06 ***
## ST_SlopeFlat     0.1545264  0.0483928   3.193  0.00146 ** 
## ST_SlopeUp      -0.2651394  0.0537090  -4.937 9.46e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3458 on 908 degrees of freedom
## Multiple R-squared:  0.5213, Adjusted R-squared:  0.5166 
## F-statistic: 109.9 on 9 and 908 DF,  p-value: < 2.2e-16

Summary of Something NEW that we have not covered in class.

  • Regression model summary ouput and interpretation
  • Check for model assumptions
  • Interpretation of the model Coefficients

Check Model Assumptions

Summary of the Model Assumptions

The residuals plot shows that the residuals appear to be randomly scattered around the horizontal line at zero, suggesting that the assumption of homoscedasticity is likely met, though there are a few potential outliers that may need further investigation. The Q-Q plot indicates that the residuals are roughly normally distributed, as the points fall approximately along the diagonal line, with minor deviations at the tails suggesting only slight deviations from normality. However, the Breusch-Pagan test yields a very small p-value (9.335e-05), leading us to reject the null hypothesis of homoscedasticity, indicating evidence of heteroscedasticity in the residuals. Despite the residuals plot visually suggesting constant variance, the Breusch-Pagan test highlights potential issues with residual variance that warrant further examination.

Interpretation

The model explains approximately 51.66% (Adjusted_R-squared) of the variability in HeartDisease. Significant predictors (with p-values < 0.05) include Age, SexM, Cholesterol, MaxHR, ExerciseAnginaY, Oldpeak, ST_SlopeFlat, and ST_SlopeUp. RestingBP is not a significant predictor in this model. The overall model is significant (p-value < 2.2e-16). These insights can help in understanding which factors are most strongly associated with heart disease according to the model.

Residuals The residuals are the differences between the observed and predicted values of the dependent variable (HeartDisease). The summary statistics of the residuals give us an idea of the distribution:

Min: -1.0947 1Q (First Quartile): -0.1770 Median: 0.0085 3Q (Third Quartile): 0.1820 Max: 1.0592 The median residual is close to zero, suggesting that the model does not have a large systematic bias. The range (from -1.0947 to 1.0592) indicates how far the residuals typically deviate from zero.

Coefficients The coefficients table shows the relationship between each predictor and the outcome variable, controlling for the other predictors.

Intercept (0.4287953): The expected value of HeartDisease when all predictors are zero. However, this might not be meaningful if zero is not a realistic value for the predictors.

Age (0.0032174, p = 0.01980): For each additional year of age, the expected increase in HeartDisease is 0.0032 units, holding other variables constant. This is statistically significant (p < 0.05), indicating age is a meaningful predictor.

SexM (0.1855887, p = 3.68e-10): Being male increases the expected value of HeartDisease by 0.1856 units compared to females, holding other variables constant. This is highly significant (p < 0.001).

RestingBP (0.0002044, p = 0.75329): Resting blood pressure does not have a statistically significant effect on HeartDisease in this model (p > 0.1).

Cholesterol (-0.0006753, p = 1.75e-09): Each unit increase in cholesterol level decreases the likelihood of having HeartDisease by 0.0006753 units, which is highly significant (p < 0.001). This negative relationship might need further investigation.

MaxHR (-0.0013184, p = 0.01530): Each unit increase in maximum heart rate achieved decreases the expected value of HeartDisease by 0.0013184 units, and this is statistically significant (p < 0.05).

ExerciseAnginaY (0.1916519, p = 1.92e-11): Presence of exercise-induced angina increases the expected value of HeartDisease by 0.1916519 units, highly significant (p < 0.001).

Oldpeak (0.0592776, p = 7.34e-06): Each unit increase in ST depression induced by exercise relative to rest increases HeartDisease by 0.0592776 units, highly significant (p < 0.001).

ST_SlopeFlat (0.1545264, p = 0.00146): Having a flat slope of the peak exercise ST segment increases HeartDisease by 0.1545264 units, significant (p < 0.01). ST_SlopeUp (-0.2651394, p = 9.46e-07): Having an upsloping ST segment decreases HeartDisease by 0.2651394 units, highly significant (p < 0.001).

Summary of Regression Model Interpretation Model Explanation:

The model explains approximately 51.66% of the variability in heart disease outcomes, as indicated by the Adjusted R-squared value.

Significant Predictors:

The following predictors are statistically significant (p-values < 0.05), indicating a meaningful relationship with heart disease:

Age: Older age is associated with an increased likelihood of heart disease.

Sex (Male): Males have a higher likelihood of heart disease compared to females.

Cholesterol: Higher cholesterol levels are significantly associated with heart disease.

MaxHR (Maximum Heart Rate Achieved): Lower maximum heart rate achieved is associated with an increased likelihood of heart disease.

Exercise-Induced Angina (ExerciseAnginaY): Presence of exercise-induced angina is associated with a higher likelihood of heart disease.

Oldpeak: Higher ST depression induced by exercise relative to rest is associated with heart disease.

ST Slope (Flat and Up): Flat ST slope is associated with a higher likelihood, while upsloping ST segment is associated with a lower likelihood of heart disease.

Non-Significant Predictor:

Resting Blood Pressure (RestingBP): This predictor does not have a statistically significant effect on heart disease in this model.

Overall Model Significance:

The model as a whole is highly significant, with a p-value less than 2.2e-16, indicating that the predictors, when considered together, reliably predict heart disease.

Conclusion:

This model provides valuable insights into the factors most strongly associated with heart disease, which can be critical for understanding risk and informing preventative measures. The significant predictors highlight key areas for monitoring and intervention in clinical practice.

Perform the Breusch-Pagan test for homoscedasticity

## 
##  studentized Breusch-Pagan test
## 
## data:  model_heart
## BP = 33.891, df = 9, p-value = 9.335e-05

Interpretation of Regression Summary Output

The regression model explains 51.66% of heart disease variability (Adjusted_R-squared = 0.5166), highlighting significant predictors: Age, SexM, Cholesterol, MaxHR, ExerciseAnginaY, Oldpeak, ST_SlopeFlat, and ST_SlopeUp. Age between 51 to 66 and being male increase heart disease risk, while higher cholesterol slightly decreases it. Lower MaxHR and presence of exercise-induced angina raise heart disease likelihood. Higher Oldpeak (ST depression) and a flat ST slope increase risk, while an upsloping ST segment decreases it. RestingBP is not significant. The model is highly reliable (p-value < 2.2e-16), aiding in effective heart disease risk assessment and management. *** # {-}


Conclusion

This model provides valuable insights into the factors most strongly associated with heart disease, which can be critical for understanding risk and informing preventative measures. The significant predictors highlight key areas for monitoring and intervention in clinical practice.


Website

Centered Image

Data URL


LS0tDQp0aXRsZTogIkRhdGE2MTIgU3VtbWVyIFByb2plY3QgUHJlc2VudGF0aW9uIEdyb3VwICMyIg0KYXV0aG9yOiAiUEVURVIgQ0hJS0EgT1pPLU9HVUVKSSwgU2hhaHJ1a2ggVmFyemdhbmksIEtldndlIE9rb2d1Ig0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHNlbGZfY29udGFpbmVkOiB0cnVlDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KA0KCWVjaG8gPSBGQUxTRSwNCgltZXNzYWdlID0gRkFMU0UsDQoJd2FybmluZyA9IEZBTFNFDQopDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoR0dhbGx5KSAgIyBGb3IgcGFpciBwbG90cw0KbGlicmFyeShjYXIpICAgICAjIEZvciBWSUYNCmxpYnJhcnkobG10ZXN0KSAgIyBGb3IgRHVyYmluLVdhdHNvbiB0ZXN0DQpsaWJyYXJ5KGNvcnJwbG90KQ0KbGlicmFyeShnZ2NvcnJwbG90KQ0KbGlicmFyeShncmlkRXh0cmEpDQpsaWJyYXJ5KG9sc3JyKQ0KbGlicmFyeShic2xpYikNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkocGxvdGx5KQ0KYGBgDQoNCiMjIEFuYWx5emluZyBGYWN0b3JzIEluZmx1ZW5jaW5nIEhlYXJ0IERpc2Vhc2UgU2V2ZXJpdHkgdXNpbmcgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24geyNUb3B9DQoqKioNCg0KPGNlbnRlcj4NCiAgPGltZyBzcmM9ImhlYXJ0X2ltYWdlLmpwZyIgYWx0PSJEYXRhIFNjaWVuY2UgVmlzdWFsaXphdGlvbiIgd2lkdGg9IjUwMCIgLz4NCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPg0KDQogIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZmVkZXNvcmlhbm8vaGVhcnQtZmFpbHVyZS1wcmVkaWN0aW9uIiB0YXJnZXQ9Il9ibGFuayI+VmlzaXQgTklIIERhdGEgU2NpZW5jZSBXZWJzaXRlPC9hPg0KPC9kaXY+DQoNCioqKg0KDQojIyBQcm9qZWN0IE92ZXJ2aWV3OiB7LnRhYnNldH0gDQojIyMgVGhpcyBwcm9qZWN0IGFpbXMgdG8gYW5hbHl6ZSB0aGUgZmFjdG9ycyBpbmZsdWVuY2luZyB0aGUgc2V2ZXJpdHkgb2YgaGVhcnQgZGlzZWFzZSB1c2luZyBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbi4gVGhlIGdvYWwgaXMgdG8gdW5kZXJzdGFuZCBob3cgdmFyaW91cyBoZWFsdGggaW5kaWNhdG9ycyBjb250cmlidXRlIHRvIHRoZSBzZXZlcml0eSBvZiBoZWFydCBkaXNlYXNlLCBtZWFzdXJlZCBvbiBhIGNvbnRpbnVvdXMgc2NhbGUuDQoqKioNCg0KIyB7LX0NCg0KKioqDQojIERhdGFzZXQgU2VsZWN0aW9uIHsudGFic2V0fQ0KU291cmNlOiBLYWdnbGUgLSBIZWFydCBGYWlsdXJlIFByZWRpY3Rpb24gRGF0YXNldA0KDQpEZXNjcmlwdGlvbjogVGhpcyBkYXRhc2V0IGNvbnRhaW5zIDEyIHZhcmlhYmxlcyBpbmNsdWRpbmcgYWdlLCBzZXgsIGNoZXN0IHBhaW4gdHlwZSwgcmVzdGluZyBibG9vZCBwcmVzc3VyZSwgc2VydW0gY2hvbGVzdGVyb2wsIGZhc3RpbmcgYmxvb2Qgc3VnYXIsIHJlc3RpbmcgZWxlY3Ryb2NhcmRpb2dyYXBoaWMgcmVzdWx0cywgbWF4aW11bSBoZWFydCByYXRlIGFjaGlldmVkLCBleGVyY2lzZS1pbmR1Y2VkIGFuZ2luYSwgb2xkcGVhayAoU1QgZGVwcmVzc2lvbiBpbmR1Y2VkIGJ5IGV4ZXJjaXNlIHJlbGF0aXZlIHRvIHJlc3QpLCBzbG9wZSBvZiB0aGUgcGVhayBleGVyY2lzZSBTVCBzZWdtZW50LCBhbmQgdGhlIG51bWJlciBvZiBtYWpvciB2ZXNzZWxzIGNvbG9yZWQgYnkgZmx1b3Jvc2NvcHkuIFRoZSB0YXJnZXQgdmFyaWFibGUgaXMgdGhlIHByZXNlbmNlIG9yIGFic2VuY2Ugb2YgaGVhcnQgZGlzZWFzZS4gVGhpcyBkYXRhc2V0IGFsaWducyB3aXRoIHRoZSBwcm9qZWN0IGd1aWRlbGluZSdzIHJlcXVpcmVtZW50cyBvZiBoYXZpbmcgYXQgbGVhc3QgMTAgdmFyaWFibGVzIGFuZCAxMDAgb2JzZXJ2YXRpb25hbCByb3dzLCB3aXRoIGJvdGggcXVhbnRpdGF0aXZlIGFuZCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuDQoNCg0KRGF0YXNldHMgTmFtZTogaGVhcnRzDQoNCldlYnNpdGUgdG8gRG93bmxvYWQgdGhlIERhdGE6DQpLYWdnbGUgLSBIZWFydCBGYWlsdXJlIFByZWRpY3Rpb24gRGF0YXNldA0KVVJMIDogaHR0cHM6Ly93d3cua2FnZ2xlLmNvbS9kYXRhc2V0cy9mZWRlc29yaWFuby9oZWFydC1mYWlsdXJlLXByZWRpY3Rpb24NCg0KIyMgRGF0YXNldHMgRGVzY3JpcHRpb24NCg0KLSBDYXJkaW92YXNjdWxhciBkaXNlYXNlcyAoQ1ZEcykgYXJlIHRoZSBudW1iZXIgMSBjYXVzZSBvZiBkZWF0aCBnbG9iYWxseSwgdGFraW5nIGFuIGVzdGltYXRlZCAxNy45IG1pbGxpb24gbGl2ZXMgZWFjaCB5ZWFyLCB3aGljaCBhY2NvdW50cyBmb3IgMzElIG9mIGFsbCBkZWF0aHMgd29ybGR3aWRlLiBGb3VyIG91dCBvZiA1Q1ZEIGRlYXRocyBhcmUgZHVlIHRvIGhlYXJ0IGF0dGFja3MgYW5kIHN0cm9rZXMsIGFuZCBvbmUtdGhpcmQgb2YgdGhlc2UgZGVhdGhzIG9jY3VyIHByZW1hdHVyZWx5IGluIHBlb3BsZSB1bmRlciA3MCB5ZWFycyBvZiBhZ2UuIEhlYXJ0IGZhaWx1cmUgaXMgYSBjb21tb24gZXZlbnQgY2F1c2VkIGJ5IENWRHMgYW5kIHRoaXMgZGF0YXNldCBjb250YWlucyAxMSBmZWF0dXJlcyB0aGF0IGNhbiBiZSB1c2VkIHRvIHByZWRpY3QgYSBwb3NzaWJsZSBoZWFydCBkaXNlYXNlLg0KDQotIFBlb3BsZSB3aXRoIGNhcmRpb3Zhc2N1bGFyIGRpc2Vhc2Ugb3Igd2hvIGFyZSBhdCBoaWdoIGNhcmRpb3Zhc2N1bGFyIHJpc2sgKGR1ZSB0byB0aGUgcHJlc2VuY2Ugb2Ygb25lIG9yIG1vcmUgcmlzayBmYWN0b3JzIHN1Y2ggYXMgaHlwZXJ0ZW5zaW9uLCBkaWFiZXRlcywgaHlwZXJsaXBpZGFlbWlhIG9yIGFscmVhZHkgZXN0YWJsaXNoZWQgZGlzZWFzZSkgbmVlZCBlYXJseSBkZXRlY3Rpb24gYW5kIG1hbmFnZW1lbnQgd2hlcmVpbiBhIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgY2FuIGJlIG9mIGdyZWF0IGhlbHAuDQoNCiMjIEF0dHJpYnV0ZSBJbmZvcm1hdGlvbg0KLSBBZ2U6IGFnZSBvZiB0aGUgcGF0aWVudCBbeWVhcnNdDQotIFNleDogc2V4IG9mIHRoZSBwYXRpZW50IFtNOiBNYWxlLCBGOiBGZW1hbGVdDQotIENoZXN0UGFpblR5cGU6IGNoZXN0IHBhaW4gdHlwZSBbVEE6IFR5cGljYWwgQW5naW5hLCBBVEE6IEF0eXBpY2FsIEFuZ2luYSwgTkFQOiBOb24tQW5naW5hbCBQYWluLCBBU1k6IEFzeW1wdG9tYXRpY10NCi0gUmVzdGluZ0JQOiByZXN0aW5nIGJsb29kIHByZXNzdXJlIFttbSBIZ10NCi0gQ2hvbGVzdGVyb2w6IHNlcnVtIGNob2xlc3Rlcm9sIFttbS9kbF0NCi0gRmFzdGluZ0JTOiBmYXN0aW5nIGJsb29kIHN1Z2FyIFsxOiBpZiBGYXN0aW5nQlMgPiAxMjAgbWcvZGwsIDA6IG90aGVyd2lzZV0NCi0gUmVzdGluZ0VDRzogcmVzdGluZyBlbGVjdHJvY2FyZGlvZ3JhbSByZXN1bHRzIFtOb3JtYWw6IE5vcm1hbCwgU1Q6IGhhdmluZyBTVC1UIHdhdmUgYWJub3JtYWxpdHkgKFQgd2F2ZSBpbnZlcnNpb25zIGFuZC9vciBTVCBlbGV2YXRpb24gb3IgZGVwcmVzc2lvbiBvZiA+IDAuMDUgbVYpLCBMVkg6IHNob3dpbmcgcHJvYmFibGUgb3IgZGVmaW5pdGUgbGVmdCB2ZW50cmljdWxhciBoeXBlcnRyb3BoeSBieSBFc3RlcycgY3JpdGVyaWFdDQotIE1heEhSOiBtYXhpbXVtIGhlYXJ0IHJhdGUgYWNoaWV2ZWQgW051bWVyaWMgdmFsdWUgYmV0d2VlbiA2MCBhbmQgMjAyXQ0KLSBFeGVyY2lzZUFuZ2luYTogZXhlcmNpc2UtaW5kdWNlZCBhbmdpbmEgW1k6IFllcywgTjogTm9dDQotIE9sZHBlYWs6IG9sZHBlYWsgPSBTVCBbTnVtZXJpYyB2YWx1ZSBtZWFzdXJlZCBpbiBkZXByZXNzaW9uXQ0KLSBTVF9TbG9wZTogdGhlIHNsb3BlIG9mIHRoZSBwZWFrIGV4ZXJjaXNlIFNUIHNlZ21lbnQgW1VwOiB1cHNsb3BpbmcsIEZsYXQ6IGZsYXQsIERvd246IGRvd25zbG9waW5nXQ0KLSBIZWFydERpc2Vhc2U6IG91dHB1dCBjbGFzcyBbMTogaGVhcnQgZGlzZWFzZSwgMDogTm9ybWFsXQ0KKioqDQoNCiMgey19DQoNCioqKg0KIyBSZXNlYXJjaCBRdWVzdGlvbnMgey50YWJzZXR9DQoxLglXaGljaCBoZWFsdGggaW5kaWNhdG9ycyBhcmUgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgcHJlZGljdG9ycyBvZiBoZWFydCBkaXNlYXNlIHNldmVyaXR5Pw0KMi4JSG93IGRvIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBzdWNoIGFzIHNleCBhbmQgY2hlc3QgcGFpbiB0eXBlIGluZmx1ZW5jZSB0aGUgcHJlZGljdGlvbiBvZiBoZWFydCBkaXNlYXNlPw0KMy4JV2hhdCBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gcXVhbnRpdGF0aXZlIHZhcmlhYmxlcyBsaWtlIGNob2xlc3Rlcm9sIGxldmVscywgcmVzdGluZyBibG9vZCBwcmVzc3VyZSwgYW5kIG1heGltdW0gaGVhcnQgcmF0ZSB3aXRoIHRoZSBzZXZlcml0eSBvZiBoZWFydCBkaXNlYXNlPw0KDQoNCg0KIyMgRXhwZWN0ZWQgT3V0Y29tZXMNClRoZSBwcm9qZWN0IGFpbXMgdG8gaWRlbnRpZnkga2V5IHByZWRpY3RvcnMgb2YgaGVhcnQgZGlzZWFzZSBzZXZlcml0eSBhbmQgcHJvdmlkZSBhIGNvbXByZWhlbnNpdmUgYW5hbHlzaXMgdGhhdCBjYW4gYWlkIGluIGVhcmx5IGRldGVjdGlvbiBhbmQgYmV0dGVyIG1hbmFnZW1lbnQgb2YgY2FyZGlvdmFzY3VsYXIgZGlzZWFzZXMuIEJ5IGxldmVyYWdpbmcgc3RhdGlzdGljYWwgYW5kIG1hY2hpbmUgbGVhcm5pbmcgdGVjaG5pcXVlcywgdGhlIGZpbmRpbmdzIHdpbGwgY29udHJpYnV0ZSB0byB0aGUgdW5kZXJzdGFuZGluZyBvZiBoZWFydCBkaXNlYXNlIHJpc2sgZmFjdG9ycyBhbmQgc3VwcG9ydCB0aGUgZGV2ZWxvcG1lbnQgb2YgcHJldmVudGl2ZSBtZWFzdXJlcw0KDQoqKioNCg0KIyB7LX0NCg0KKioqDQojIERhdGEgSW1wb3J0IGFuZCBDb252ZXJzaW9uIHsudGFic2V0fQ0KIyMgUHVycG9zZQ0KDQpEYXRhIEltcG9ydDogVG8gbG9hZCB0aGUgZGF0YXNldCBpbnRvIFIgZm9yIGFuYWx5c2lzLg0KQ2hlY2sgZm9yIE1pc3NpbmcgVmFsdWVzOiBUbyBlbnN1cmUgZGF0YSBjb21wbGV0ZW5lc3MgYW5kIGludGVncml0eS4NCkRhdGEgQ29udmVyc2lvbjogVG8gZW5zdXJlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhcmUgdHJlYXRlZCBhcHByb3ByaWF0ZWx5IGluIHRoZSBhbmFseXNpcy4NCg0KYGBge3J9DQojIEltcG9ydCB0aGUgZGF0YXNldA0KDQoNCmhlYXJ0X2RhdGEgPC0gcmVhZF9jc3YoIkM6L1VzZXJzL2F1dXNlci9EZXNrdG9wL0RhdGE2MTIgUHJvaiBQcm9wb3NhbC9oZWFydC5jc3YiLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKQ0KDQpoZWFkKGhlYXJ0X2RhdGEpDQpzdW1tYXJ5KGhlYXJ0X2RhdGEpDQpgYGANCg0KIERhdGEgVGliYmxlLg0KDQpgYGB7cn0NCmlzX3RpYmJsZShoZWFydF9kYXRhKQ0KYGBgDQoNClRpZHkgRGF0YQ0KDQpgYGB7cn0NCnN1bShpcy5uYShoZWFydF9kYXRhKSkNCmBgYA0KDQpUbyBpZGVudGlmeSBhbmQgY2hhcmFjdGVyaXplIHRoZSBkYXRhc2V0IHRob3JvdWdobHksIHdlIGNhbiB1dGlsaXplIHNldmVyYWwgUiBmdW5jdGlvbnMgdGhhdCBwcm92aWRlIGRldGFpbGVkIGluc2lnaHRzIGludG8gdGhlIHN0cnVjdHVyZSwgc3VtbWFyeSBzdGF0aXN0aWNzLCBkaXN0cmlidXRpb24sIGFuZCByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGhlIHZhcmlhYmxlcw0KDQojIyBVbmRlcnN0YW5kaW5nIHRoZSBEYXRhIFN0cnVjdHVyZSANCg0KYGBge3J9DQojIENoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgdGhlIGRhdGENCnN0cihoZWFydF9kYXRhKQ0KDQojIyMgRXhwbGFuYXRpb246IFRoZSBzdHIoKSBmdW5jdGlvbiBnaXZlcyBhIGNvbXBhY3Qgb3ZlcnZpZXcgb2YgdGhlIGRhdGFzZXQsIHNob3dpbmcgdGhlIHR5cGVzIG9mIGVhY2ggdmFyaWFibGUgYW5kIHRoZSBmaXJzdCBmZXcgZW50cmllcywgd2hpY2ggaXMgZXNzZW50aWFsIGZvciB1bmRlcnN0YW5kaW5nIHRoZSBkYXRhIHR5cGVzIGFuZCBzdHJ1Y3R1cmUuDQpgYGANCiMjIERhdGEgUHJlcHJvY2Vzc2luZw0KDQojIyMgQ29udmVydCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgdG8gZHVtbXkgdmFyaWFibGVzDQoNCmBgYHtyfQ0KIyBDb252ZXJ0IGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB0byBkdW1teSB2YXJpYWJsZXMNCg0KaGVhcnRfZGF0YTIgPC0gaGVhcnRfZGF0YSAlPiUNCiAgbXV0YXRlKFNleCA9IGZhY3RvcihoZWFydF9kYXRhJFNleCksDQogICAgICAgICBDaGVzdFBhaW5UeXBlID0gZmFjdG9yKGhlYXJ0X2RhdGEkQ2hlc3RQYWluVHlwZSksDQogICAgICAgICBGYXN0aW5nQlMgPSBmYWN0b3IoaGVhcnRfZGF0YSRGYXN0aW5nQlMpLA0KICAgICAgICAgUmVzdGluZ0VDRyA9IGZhY3RvcihoZWFydF9kYXRhJFJlc3RpbmdFQ0cpLA0KICAgICAgICAgRXhlcmNpc2VBbmdpbmEgPSBmYWN0b3IoaGVhcnRfZGF0YSRFeGVyY2lzZUFuZ2luYSksDQogICAgICAgICBTVF9TbG9wZSA9IGZhY3RvcihoZWFydF9kYXRhJFNUX1Nsb3BlKSwNCiAgICAgICAgIEhlYXJ0RGlzZWFzZSA9IGZhY3RvcihoZWFydF9kYXRhJEhlYXJ0RGlzZWFzZSkpDQoNCiMgVXNlIG1vZGVsLm1hdHJpeCgpIHRvIGNyZWF0ZSBkdW1teSB2YXJpYWJsZXMNCiMgRXhjbHVkZSB0aGUgaW50ZXJjZXB0IHRvIGdldCBmdWxsIHNldCBvZiBkdW1teSB2YXJpYWJsZXMNCmR1bW15X3ZhcmlhYmxlcyA8LSBtb2RlbC5tYXRyaXgofiBTZXggKyBDaGVzdFBhaW5UeXBlICsgRmFzdGluZ0JTICsgUmVzdGluZ0VDRyArIEV4ZXJjaXNlQW5naW5hICsgU1RfU2xvcGUgKyBIZWFydERpc2Vhc2UgLSAxLCBkYXRhID0gaGVhcnRfZGF0YTIpDQoNCiMgQ29udmVydCB0byBhIGRhdGEgZnJhbWUgZm9yIGVhc2llciB2aWV3aW5nDQpkdW1teV92YXJpYWJsZXNfZGYgPC0gYXMudGliYmxlKGR1bW15X3ZhcmlhYmxlcykNCg0KIyBWaWV3IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZHVtbXkgdmFyaWFibGVzDQpkdW1teV92YXJpYWJsZXNfZGYNCg0KDQojIyMgSG93IG1vZGVsLm1hdHJpeCgpIFdvcmtzDQojIyMgSW50ZXJjZXB0IEhhbmRsaW5nOg0KDQojIyMgQnkgZGVmYXVsdCwgbW9kZWwubWF0cml4KCkgaW5jbHVkZXMgYW4gaW50ZXJjZXB0IHRlcm0gKGEgY29sdW1uIG9mIG9uZXMpIHVubGVzcyBleHBsaWNpdGx5IHJlbW92ZWQgYnkgdXNpbmcgLTEgaW4gdGhlIGZvcm11bGEuDQojIyMgVGhlIGludGVyY2VwdCByZXByZXNlbnRzIHRoZSBiYXNlbGluZSBsZXZlbCBvZiB0aGUgbW9kZWwgYW5kIGlzIGNydWNpYWwgZm9yIGNhbGN1bGF0aW5nICMjIyB0aGUgYmFzZWxpbmUgbWVhbiBpbiBsaW5lYXIgbW9kZWxzLg0KIyMjIER1bW15IFZhcmlhYmxlcyBmb3IgRmFjdG9yczoNCg0KIyMjIENhdGVnb3JpY2FsIHZhcmlhYmxlcyAoZmFjdG9ycykgYXJlIGNvbnZlcnRlZCBpbnRvIGEgc2V0IG9mIGJpbmFyeSAoMC8xKSBjb2x1bW5zLCBvbmUgZm9yIGVhY2ggbGV2ZWwgb2YgdGhlIGZhY3RvciwgbWludXMgb25lIGxldmVsIHRvIGF2b2lkIHRoZSBkdW1teSB2YXJpYWJsZSB0cmFwIChwZXJmZWN0IG11bHRpY29sbGluZWFyaXR5KS4NCiMjIyBUaGlzIGV4Y2x1c2lvbiBvZiBvbmUgbGV2ZWwgaXMgcmVmZXJyZWQgdG8gYXMgdGhlIHJlZmVyZW5jZSBsZXZlbCwgYW5kIGFsbCBjb21wYXJpc29ucyBhcmUgbWFkZSByZWxhdGl2ZSB0byB0aGlzIGxldmVsLg0KIyMjIEN1c3RvbSBDb250cmFzdHM6DQoNCiMjIyBVc2VycyBjYW4gc3BlY2lmeSBjdXN0b20gY29udHJhc3RzIGZvciBmYWN0b3JzIHVzaW5nIHRoZSBjb250cmFzdHMoKSBmdW5jdGlvbiwgYWxsb3dpbmcgZm9yIGFsdGVybmF0aXZlIGVuY29kaW5nIHNjaGVtZXMgc3VjaCBhcyBIZWxtZXJ0IG9yIHN1bSBjb250cmFzdHMuDQojIyMgSW50ZXJhY3Rpb24gVGVybXM6DQoNCiMjIyBtb2RlbC5tYXRyaXgoKSBjYW4gaGFuZGxlIGludGVyYWN0aW9uIHRlcm1zIHNwZWNpZmllZCBpbiB0aGUgZm9ybXVsYSwgY3JlYXRpbmcgY29sdW1ucyB0aGF0IHJlcHJlc2VudCB0aGUgaW50ZXJhY3Rpb24gYmV0d2VlbiB0d28gb3IgbW9yZSB2YXJpYWJsZXMuDQpgYGANCioqKg0KIyB7LX0NCioqKg0KIyBDYXRlZ29yaWNhbCBhbmQgUXVhbnRpdGF0aXZlIFZhcmlhYmxlIFBsb3RzKEVEQSkgey50YWJzZXR9DQoNCiBUbyBnZW5lcmF0ZSBpbnNpZ2h0ZnVsIHBsb3RzIHVzaW5nIGdncGxvdDIsIHdlIHdpbGwgY3JlYXRlIHZpc3VhbGl6YXRpb25zIHRoYXQgaGlnaGxpZ2h0IHJlbGF0aW9uc2hpcHMgYW5kIHRyZW5kcyBiZXR3ZWVuIGNhdGVnb3JpY2FsIGFuZCBxdWFudGl0YXRpdmUgdmFyaWFibGVzIGluIHRoZSBoZWFydCBkaXNlYXNlIGRhdGFzZXQuIFRoZXNlIHBsb3RzIHdpbGwgaW5jbHVkZSBoaXN0b2dyYW1zLCBib3hwbG90cywgYW5kIHNjYXR0ZXIgcGxvdHMgd2l0aCB0cmVuZCBsaW5lcywgd2hpY2ggY2FuIGhlbHAgdXMgdW5jb3ZlciBwYXR0ZXJucyBhbmQgaW5zaWdodHMgaW4gdGhlIGRhdGEuDQoNCg0KIFZpc3VhbGl6YXRpb24gR29hbHMNCg0KIERpc2NyaXB0aW9uDQogRGlzdHJpYnV0aW9uIG9mIEFnZSBieSBIZWFydCBEaXNlYXNlIFN0YXR1czogVXNlIGhpc3RvZ3JhbXMgdG8gc2hvdyBob3cgYWdlIGlzIGRpc3RyaWJ1dGVkIGFtb25nIHRob3NlIHdpdGggYW5kIHdpdGhvdXQgaGVhcnQgZGlzZWFzZS4NCkJveHBsb3RzIG9mIENob2xlc3Rlcm9sIGJ5IENoZXN0IFBhaW4gVHlwZTogQ29tcGFyZSBjaG9sZXN0ZXJvbCBsZXZlbHMgYWNyb3NzIGRpZmZlcmVudCB0eXBlcyBvZiBjaGVzdCBwYWluLg0KU2NhdHRlciBQbG90IG9mIE1heCBIZWFydCBSYXRlIHZzLiBBZ2U6IEV4YW1pbmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgbWF4aW11bSBoZWFydCByYXRlLCBkaWZmZXJlbnRpYXRlZCBieSBoZWFydCBkaXNlYXNlIHN0YXR1cy4NCkJhciBQbG90IG9mIEhlYXJ0IERpc2Vhc2UgYnkgU2V4OiBTaG93IHRoZSBwcm9wb3J0aW9uIG9mIGhlYXJ0IGRpc2Vhc2UgYWNyb3NzIGdlbmRlcnMuDQoNCg0KDQojIyBEaXN0cmlidXRpb24gb2YgQWdlIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzIHsudGFic2V0fQ0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dwbG90MikNCg0KIyBIaXN0b2dyYW0gb2YgQWdlIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzDQpwMSA8LSBnZ3Bsb3QoaGVhcnRfZGF0YTIsIGFlcyh4ID0gQWdlLCBmaWxsID0gSGVhcnREaXNlYXNlKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDUsIHBvc2l0aW9uID0gImRvZGdlIiwgYWxwaGEgPSAwLjcpICsNCiAgbGFicyh0aXRsZSA9ICJBZ2UgRGlzdHJpYnV0aW9uIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzIiwgDQogICAgICAgeCA9ICJBZ2UiLCANCiAgICAgICB5ID0gIkNvdW50IikgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJkYXJrYmx1ZSIsICJwdXJwbGUiKSkNCg0KZ2dwbG90bHkocDEpDQoNCiNFeHBsYW5hdGlvbjoNCiMgVGhlIGhpc3RvZ3JhbSBzaG93cyB0aGUgYWdlIGRpc3RyaWJ1dGlvbiBmb3IgcGF0aWVudHMgd2l0aCBhbmQgd2l0aG91dCBoZWFydCBkaXNlYXNlLCB1c2luZyBmaWxsIHRvIGRpZmZlcmVudGlhdGUgdGhlIGdyb3Vwcy4NCiMgYmlud2lkdGggPSA1IGdyb3VwcyBhZ2VzIGludG8gNS15ZWFyIGludGVydmFscyBmb3IgY2xhcml0eS4NCiMgcG9zaXRpb24gPSAiZG9kZ2UiIHNlcGFyYXRlcyB0aGUgYmFycyBmb3IgYmV0dGVyIGNvbXBhcmlzb24uDQoNCiMgQm94cGxvdHMgb2YgQ2hvbGVzdGVyb2wgYnkgQ2hlc3QgUGFpbiBUeXBlIHsudGFic2V0fQ0KDQojIEJveHBsb3Qgb2YgQ2hvbGVzdGVyb2wgYnkgQ2hlc3QgUGFpbiBUeXBlDQpwMiA8LSBnZ3Bsb3QoaGVhcnRfZGF0YTIsIGFlcyh4ID0gQ2hlc3RQYWluVHlwZSwgeSA9IENob2xlc3Rlcm9sLCBmaWxsID0gQ2hlc3RQYWluVHlwZSkpICsNCiAgZ2VvbV9ib3hwbG90KCkgKw0KICBsYWJzKHRpdGxlID0gIkNob2xlc3Rlcm9sIExldmVscyBieSBDaGVzdCBQYWluIFR5cGUiLCANCiAgICAgICB4ID0gIkNoZXN0IFBhaW4gVHlwZSIsIA0KICAgICAgIHkgPSAiQ2hvbGVzdGVyb2wgKG1nL2RsKSIpICsNCiAgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJQYXN0ZWwxIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQoNCmdncGxvdGx5KHAyKQ0KDQojIyMgRXhwbGFuYXRpb246DQoNCiMjIyBCb3hwbG90cyBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgY2hvbGVzdGVyb2wgbGV2ZWxzIGFjcm9zcyBkaWZmZXJlbnQgdHlwZXMgb2YgY2hlc3QgcGFpbi4NCiMjIyBUaGlzIHZpc3VhbGl6YXRpb24gaGVscHMgaWRlbnRpZnkgYW55IGRpZmZlcmVuY2VzIGluIGNob2xlc3Rlcm9sIGxldmVscyBhbW9uZyB0aGUgcGFpbiB0eXBlcy4NCg0KIyMgU2NhdHRlciBQbG90IG9mIE1heCBIZWFydCBSYXRlIHZzLiBBZ2UgDQoNCg0KIyBTY2F0dGVyIFBsb3Qgb2YgTWF4IEhlYXJ0IFJhdGUgdnMuIEFnZSwgY29sb3JlZCBieSBIZWFydCBEaXNlYXNlIFN0YXR1cw0KcDMgPC0gZ2dwbG90KGhlYXJ0X2RhdGEyLCBhZXMoeCA9IEFnZSwgeSA9IE1heEhSLCBjb2xvciA9IEhlYXJ0RGlzZWFzZSkpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJibGFjayIpICsNCiAgbGFicyh0aXRsZSA9ICJNYXggSGVhcnQgUmF0ZSB2cy4gQWdlIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzIiwgDQogICAgICAgeCA9ICJBZ2UiLCANCiAgICAgICB5ID0gIk1heCBIZWFydCBSYXRlIikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygicmVkIiwgInB1cnBsZSIpKQ0KDQpnZ3Bsb3RseShwMykNCg0KIyMjIEV4cGxhbmF0aW9uOg0KDQojIyMgQSBzY2F0dGVyIHBsb3Qgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGFnZSBhbmQgbWF4aW11bSBoZWFydCByYXRlLCB3aXRoIGEgbGluZWFyIHRyZW5kIGxpbmUgKGdlb21fc21vb3RoKS4NCiMjIyBQb2ludHMgYXJlIGNvbG9yZWQgYnkgaGVhcnQgZGlzZWFzZSBzdGF0dXMsIHdoaWNoIGNhbiBoZWxwIGlkZW50aWZ5IHRyZW5kcyBhbmQgcGF0dGVybnMgYmV0d2VlbiB0aGUgdmFyaWFibGVzLg0KDQojIyBCYXIgUGxvdCBvZiBIZWFydCBEaXNlYXNlIGJ5IFNleCANCg0KDQojIEJhciBQbG90IG9mIEhlYXJ0IERpc2Vhc2UgYnkgU2V4DQpwNCA8LSBnZ3Bsb3QoaGVhcnRfZGF0YTIsIGFlcyh4ID0gU2V4LCBmaWxsID0gSGVhcnREaXNlYXNlKSkgKw0KICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJmaWxsIikgKw0KICBsYWJzKHRpdGxlID0gIlByb3BvcnRpb24gb2YgSGVhcnQgRGlzZWFzZSBieSBTZXgiLCANCiAgICAgICB4ID0gIlNleCIsIA0KICAgICAgIHkgPSAiUHJvcG9ydGlvbiIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZGOTk5OSIsICJwdXJwbGUiKSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50KQ0KDQpnZ3Bsb3RseShwNCkNCg0KIyMjIEV4cGxhbmF0aW9uOg0KDQojIyMgQSBiYXIgcGxvdCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiBoZWFydCBkaXNlYXNlIHdpdGhpbiBlYWNoIGdlbmRlci4NCiMjIyBwb3NpdGlvbiA9ICJmaWxsIiBub3JtYWxpemVzIGVhY2ggYmFyIHRvIDEwMCUsIGFsbG93aW5nIHVzIHRvIGNvbXBhcmUgcHJvcG9ydGlvbnMuDQoNCmBgYA0KDQojIyBEZXNjcmlwdGlvbiBhbmQgSW50ZXJwcmV0YXRpb24gey50YWJzZXR9DQoNCiBBZ2UgRGlzdHJpYnV0aW9uIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzDQoNCiBEZXNjcmlwdGlvbjoNClRoaXMgaGlzdG9ncmFtIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgYWdlcyBmb3IgaW5kaXZpZHVhbHMgd2l0aCBhbmQgd2l0aG91dCBoZWFydCBkaXNlYXNlLiBUaGUgYmx1ZSBiYXJzIHJlcHJlc2VudCBpbmRpdmlkdWFscyB3aXRob3V0IGhlYXJ0IGRpc2Vhc2UgKEhlYXJ0RGlzZWFzZSA9IDApLCBhbmQgdGhlIHB1cnBsZSBiYXJzIHJlcHJlc2VudCBpbmRpdmlkdWFscyB3aXRoIGhlYXJ0IGRpc2Vhc2UgKEhlYXJ0RGlzZWFzZSA9IDEpLg0KDQogSW50ZXJwcmV0YXRpb246DQoNCkluZGl2aWR1YWxzIHdpdGggaGVhcnQgZGlzZWFzZSBhcmUgZ2VuZXJhbGx5IG9sZGVyLCB3aXRoIGEgbm90aWNlYWJsZSBpbmNyZWFzZSBpbiBoZWFydCBkaXNlYXNlIHByZXZhbGVuY2Ugc3RhcnRpbmcgZnJvbSB0aGUgYWdlIG9mIDQwLg0KVGhlIHBlYWsgcHJldmFsZW5jZSBmb3IgaW5kaXZpZHVhbHMgd2l0aCBoZWFydCBkaXNlYXNlIGlzIGFyb3VuZCA1MCB0byA2MCB5ZWFycy4NClRoZXJlIGFyZSBmZXdlciB5b3VuZyBpbmRpdmlkdWFscyAodW5kZXIgNDApIHdpdGggaGVhcnQgZGlzZWFzZSwgaW5kaWNhdGluZyBhZ2UgYXMgYSBzaWduaWZpY2FudCBmYWN0b3IgaW4gaGVhcnQgZGlzZWFzZSBwcmV2YWxlbmNlLg0KDQogQ2hvbGVzdGVyb2wgTGV2ZWxzIGJ5IENoZXN0IFBhaW4gVHlwZQ0KDQogRGVzY3JpcHRpb246DQpUaGlzIGJveCBwbG90IHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgY2hvbGVzdGVyb2wgbGV2ZWxzIGZvciBkaWZmZXJlbnQgY2hlc3QgcGFpbiB0eXBlcyAoQVNZOiBBc3ltcHRvbWF0aWMsIEFUQTogQXR5cGljYWwgQW5naW5hLCBOQVA6IE5vbi1BbmdpbmFsIFBhaW4sIFRBOiBUeXBpY2FsIEFuZ2luYSkuDQoNCiBJbnRlcnByZXRhdGlvbjoNCg0KSW5kaXZpZHVhbHMgd2l0aCBhc3ltcHRvbWF0aWMgKEFTWSkgY2hlc3QgcGFpbiBoYXZlIGEgd2lkZXIgcmFuZ2Ugb2YgY2hvbGVzdGVyb2wgbGV2ZWxzLCB3aXRoIG1hbnkgb3V0bGllcnMgaW5kaWNhdGluZyBoaWdoZXIgY2hvbGVzdGVyb2wuDQpUaG9zZSB3aXRoIHR5cGljYWwgYW5naW5hIChUQSkgYW5kIG5vbi1hbmdpbmFsIHBhaW4gKE5BUCkgdGVuZCB0byBoYXZlIGhpZ2hlciBjaG9sZXN0ZXJvbCBsZXZlbHMgY29tcGFyZWQgdG8gb3RoZXIgY2hlc3QgcGFpbiB0eXBlcy4NCkF0eXBpY2FsIGFuZ2luYSAoQVRBKSBzaG93cyBhIG1vcmUgY29uc2lzdGVudCByYW5nZSBvZiBjaG9sZXN0ZXJvbCBsZXZlbHMgd2l0aCBmZXdlciBleHRyZW1lIHZhbHVlcy4NCiBNYXggSGVhcnQgUmF0ZSB2cy4gQWdlIGJ5IEhlYXJ0IERpc2Vhc2UgU3RhdHVzDQoNCiBEZXNjcmlwdGlvbjoNClRoaXMgc2NhdHRlciBwbG90IHNob3dzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtYXhpbXVtIGhlYXJ0IHJhdGUgYW5kIGFnZSwgd2l0aCBkaWZmZXJlbnQgY29sb3JzIHJlcHJlc2VudGluZyBoZWFydCBkaXNlYXNlIHN0YXR1cyAoUmVkOiBObyBoZWFydCBkaXNlYXNlLCBQdXJwbGU6IEhlYXJ0IGRpc2Vhc2UpLg0KDQogSW50ZXJwcmV0YXRpb246DQoNClRoZXJlIGlzIGEgZ2VuZXJhbCBkZWNsaW5lIGluIG1heGltdW0gaGVhcnQgcmF0ZSB3aXRoIGluY3JlYXNpbmcgYWdlIGZvciBib3RoIGdyb3Vwcy4NCkluZGl2aWR1YWxzIHdpdGhvdXQgaGVhcnQgZGlzZWFzZSAocmVkKSB0ZW5kIHRvIGhhdmUgaGlnaGVyIG1heGltdW0gaGVhcnQgcmF0ZXMgY29tcGFyZWQgdG8gdGhvc2Ugd2l0aCBoZWFydCBkaXNlYXNlIChwdXJwbGUpLg0KVGhpcyBuZWdhdGl2ZSBjb3JyZWxhdGlvbiBzdWdnZXN0cyB0aGF0IGFzIGluZGl2aWR1YWxzIGFnZSwgdGhlaXIgbWF4aW11bSBoZWFydCByYXRlIGRlY3JlYXNlcywgYW5kIHRob3NlIHdpdGggbG93ZXIgbWF4aW11bSBoZWFydCByYXRlcyBhcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSBoZWFydCBkaXNlYXNlLg0KDQpQcm9wb3J0aW9uIG9mIEhlYXJ0IERpc2Vhc2UgYnkgU2V4DQoNCkRlc2NyaXB0aW9uOg0KVGhpcyBiYXIgcGxvdCBzaG93cyB0aGUgcHJvcG9ydGlvbiBvZiBoZWFydCBkaXNlYXNlIHByZXZhbGVuY2UgYnkgc2V4LiBUaGUgcGluayBiYXJzIHJlcHJlc2VudCBpbmRpdmlkdWFscyB3aXRob3V0IGhlYXJ0IGRpc2Vhc2UgKEhlYXJ0RGlzZWFzZSA9IDApLCBhbmQgdGhlIHB1cnBsZSBiYXJzIHJlcHJlc2VudCBpbmRpdmlkdWFscyB3aXRoIGhlYXJ0IGRpc2Vhc2UgKEhlYXJ0RGlzZWFzZSA9IDEpLg0KDQpJbnRlcnByZXRhdGlvbjoNCg0KTWFsZXMgKE0pIGhhdmUgYSBoaWdoZXIgcHJvcG9ydGlvbiBvZiBoZWFydCBkaXNlYXNlIGNvbXBhcmVkIHRvIGZlbWFsZXMgKEYpLg0KVGhlIG1ham9yaXR5IG9mIGZlbWFsZXMgZG8gbm90IGhhdmUgaGVhcnQgZGlzZWFzZSwgd2hpbGUgYSBzaWduaWZpY2FudCBwcm9wb3J0aW9uIG9mIG1hbGVzIGRvLg0KVGhpcyBpbmRpY2F0ZXMgdGhhdCBzZXggaXMgYW4gaW1wb3J0YW50IGZhY3Rvciwgd2l0aCBtYWxlcyBiZWluZyBtb3JlIHN1c2NlcHRpYmxlIHRvIGhlYXJ0IGRpc2Vhc2UuDQpPdmVyYWxsIEludGVycHJldGF0aW9uDQpUaGVzZSB2aXN1YWxpemF0aW9ucyBwcm92aWRlIGltcG9ydGFudCBpbnNpZ2h0cyBpbnRvIHRoZSBmYWN0b3JzIGFzc29jaWF0ZWQgd2l0aCBoZWFydCBkaXNlYXNlOg0KDQpBZ2U6IE9sZGVyIGFnZSBncm91cHMgaGF2ZSBoaWdoZXIgaGVhcnQgZGlzZWFzZSBwcmV2YWxlbmNlLg0KQ2hvbGVzdGVyb2w6IEhpZ2hlciBjaG9sZXN0ZXJvbCBsZXZlbHMgYXJlIG1vcmUgY29tbW9uIGluIGluZGl2aWR1YWxzIHdpdGggY2VydGFpbiB0eXBlcyBvZiBjaGVzdCBwYWluLg0KTWF4IEhlYXJ0IFJhdGU6IExvd2VyIG1heGltdW0gaGVhcnQgcmF0ZXMgYXJlIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgaGVhcnQgZGlzZWFzZSBwcmV2YWxlbmNlLCBlc3BlY2lhbGx5IGluIG9sZGVyIGluZGl2aWR1YWxzLg0KU2V4OiBNYWxlcyBhcmUgYXQgYSBoaWdoZXIgcmlzayBvZiBkZXZlbG9waW5nIGhlYXJ0IGRpc2Vhc2UgY29tcGFyZWQgdG8gZmVtYWxlcy4NCg0KKioqDQoNCiMgey19DQoqKioNCg0KIyMgSW50ZXJhY3RpdmUgVGFibGUgDQoNCmBgYHtyIEludGVyYWN0aXZlIFRhYmxlfQ0KZGF0YXRhYmxlKGhlYXJ0X2RhdGEyLCBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gMTAsIGF1dG9XaWR0aCA9IFRSVUUpKQ0KDQpgYGANCioqKg0KIyB7LX0NCioqKg0KIyBJbnRlcnByZXRhdGlvbiBvZiB0aGUgUXVhbnRpdGF0aXZlIGFuZCBRdWFsaXRhdGl2ZSBQbG90cyB7LnRhYnNldH0NCiMjIFRoZSB2aXN1YWxpemF0aW9ucyByZXZlYWwgdGhhdCBvbGRlciBhZ2UgZ3JvdXBzIChlc3BlY2lhbGx5IHRob3NlIG92ZXIgNDApIGhhdmUgYSBoaWdoZXIgcHJldmFsZW5jZSBvZiBoZWFydCBkaXNlYXNlLCB3aXRoIHBlYWsgY2FzZXMgYXJvdW5kIDUwLTYwIHllYXJzLiBDaG9sZXN0ZXJvbCBsZXZlbHMgdmFyeSBzaWduaWZpY2FudGx5IHdpdGggY2hlc3QgcGFpbiB0eXBlcywgd2l0aCBhc3ltcHRvbWF0aWMgaW5kaXZpZHVhbHMgc2hvd2luZyBhIHdpZGUgcmFuZ2UgYW5kIGhpZ2hlciBsZXZlbHMsIHdoaWxlIHR5cGljYWwgYW5naW5hIGFuZCBub24tYW5naW5hbCBwYWluIGFyZSBhbHNvIGFzc29jaWF0ZWQgd2l0aCBoaWdoZXIgY2hvbGVzdGVyb2wuIEEgZGVjbGluaW5nIG1heGltdW0gaGVhcnQgcmF0ZSB3aXRoIGFnZSBpcyBvYnNlcnZlZCwgYW5kIHRob3NlIHdpdGggaGVhcnQgZGlzZWFzZSBnZW5lcmFsbHkgaGF2ZSBsb3dlciBtYXhpbXVtIGhlYXJ0IHJhdGVzLiBBZGRpdGlvbmFsbHksIG1hbGVzIGFyZSBhdCBhIGhpZ2hlciByaXNrIG9mIGhlYXJ0IGRpc2Vhc2UgY29tcGFyZWQgdG8gZmVtYWxlcywgaGlnaGxpZ2h0aW5nIHRoZSBpbXBvcnRhbmNlIG9mIGFnZSwgY2hvbGVzdGVyb2wsIG1heGltdW0gaGVhcnQgcmF0ZSwgYW5kIHNleCBhcyBjcml0aWNhbCBmYWN0b3JzIGluIGhlYXJ0IGRpc2Vhc2UgcHJldmFsZW5jZS4uDQoqKioNCiMgey19DQoNCioqKg0KIyBDb3JyZWxhdGlvbiB7LnRhYnNldH0NCg0KVG8gVmlzdWFsaXplIHRoZSBDb3JyZWxhdGlvbiBNYXRyaXgsIHdlIFVzZSBhIGhlYXRtYXAgdG8gdmlzdWFsaXplIHRoZSBjb3JyZWxhdGlvbnMsIGhpZ2hsaWdodGluZyBib3RoIHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMuDQoNCg0KIyMgVmlzdWFsaXplIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggdXNpbmcgY29ycnBsb3Qgey50YWJzZXR9DQoNCmBgYHtyfQ0KIyBDb21wdXRlIGNvcnJlbGF0aW9uIG1hdHJpeCBmb3IgbnVtZXJpYyB2YXJpYWJsZXMNCm51bWVyaWNfdmFycyA8LSBoZWFydF9kYXRhICU+JQ0KICBzZWxlY3RfaWYoaXMubnVtZXJpYykgIyBTZWxlY3Qgb25seSBudW1lcmljIGNvbHVtbnMNCg0KY29ycmVsYXRpb25fbWF0cml4IDwtIGNvcihudW1lcmljX3ZhcnMsIHVzZSA9ICJjb21wbGV0ZS5vYnMiKSAjIENvbXB1dGUgY29ycmVsYXRpb25zDQoNCg0KY29ycnBsb3QoY29ycmVsYXRpb25fbWF0cml4LCBtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwgDQogICAgICAgICBvcmRlciA9ICJoY2x1c3QiLCB0bC5jb2wgPSAiYmxhY2siLCB0bC5zcnQgPSA0NSwgDQogICAgICAgICBhZGRDb2VmLmNvbCA9ICJibGFjayIsIG51bWJlci5jZXggPSAwLjcsDQogICAgICAgICBjb2wgPSBjb2xvclJhbXBQYWxldHRlKGMoInJlZCIsICJ3aGl0ZSIsICJibHVlIikpKDIwMCkpDQoNCiMgRXhwbGFuYXRpb24NCiNTZWxlY3QgTnVtZXJpYyBWYXJpYWJsZXM6IFdlIHVzZSBzZWxlY3RfaWYoaXMubnVtZXJpYykgdG8gY2hvb3NlIG9ubHkgdGhlIG51bWVyaWMgY29sdW1ucyBmcm9tIHRoZSBkYXRhc2V0IGZvciBjb3JyZWxhdGlvbiBhbmFseXNpcy4NCg0KI0NvbXB1dGUgQ29ycmVsYXRpb25zOiBUaGUgY29yKCkgZnVuY3Rpb24gY2FsY3VsYXRlcyB0aGUgcGFpcndpc2UgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGZvciB0aGUgc2VsZWN0ZWQgbnVtZXJpYyB2YXJpYWJsZXMuIFRoZSB1c2UgPSAiY29tcGxldGUub2JzIiBhcmd1bWVudCBlbnN1cmVzIHRoYXQgb25seSBjb21wbGV0ZSBvYnNlcnZhdGlvbnMgKHJvd3Mgd2l0aG91dCBtaXNzaW5nIHZhbHVlcykgYXJlIHVzZWQgaW4gdGhlIGNhbGN1bGF0aW9uLg0KDQojVmlzdWFsaXplIHdpdGggY29ycnBsb3Q6DQojbWV0aG9kID0gImNvbG9yIjogQ29sb3JzIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXggY2VsbHMgYmFzZWQgb24gY29ycmVsYXRpb24gc3RyZW5ndGggYW5kIGRpcmVjdGlvbi4NCiN0eXBlID0gInVwcGVyIjogRGlzcGxheXMgb25seSB0aGUgdXBwZXIgdHJpYW5nbGUgb2YgdGhlIG1hdHJpeCB0byBhdm9pZCByZWR1bmRhbmN5Lg0KI29yZGVyID0gImhjbHVzdCI6IE9yZGVycyB0aGUgbWF0cml4IGJhc2VkIG9uIGhpZXJhcmNoaWNhbCBjbHVzdGVyaW5nLCBncm91cGluZyBzdHJvbmdseSAjY29ycmVsYXRlZCB2YXJpYWJsZXMgdG9nZXRoZXIuDQojdGwuY29sID0gImJsYWNrIiBhbmQgdGwuc3J0ID0gNDU6IFNldCB0aGUgdGV4dCBsYWJlbCBjb2xvciBhbmQgcm90YXRpb24gYW5nbGUgZm9yIGJldHRlciByZWFkYWJpbGl0eS4NCiNhZGRDb2VmLmNvbCA9ICJibGFjayI6IEFkZHMgdGhlIGNvcnJlbGF0aW9uIGNvZWZmaWNpZW50cyBhcyB0ZXh0IG9uIHRoZSBwbG90Lg0KI2NvbCA9IGNvbG9yUmFtcFBhbGV0dGUoYygicmVkIiwgIndoaXRlIiwgImJsdWUiKSkoMjAwKTogRGVmaW5lcyB0aGUgY29sb3IgZ3JhZGllbnQsIHdpdGggcmVkIGZvciBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMsIGJsdWUgZm9yIHBvc2l0aXZlIGNvcnJlbGF0aW9ucywgYW5kIHdoaXRlIGZvciB6ZXJvIGNvcnJlbGF0aW9uLg0KDQpgYGANCg0KIyMgSW50ZXJwcmV0YXRpb24gb2YgQ29ycmVsYXRpb24gTWF0cml4IHsudGFic2V0fQ0KVGhpcyBjb3JyZWxhdGlvbiBtYXRyaXggdmlzdWFsaXplcyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIGRpZmZlcmVudCB2YXJpYWJsZXMgaW4gdGhlIGRhdGFzZXQuIFRoZSBjb2xvciBzY2FsZSBvbiB0aGUgcmlnaHQgaW5kaWNhdGVzIHRoZSBzdHJlbmd0aCBhbmQgZGlyZWN0aW9uIG9mIHRoZSBjb3JyZWxhdGlvbnMsIHdpdGggdmFsdWVzIHJhbmdpbmcgZnJvbSAtMSB0byAxLiBQb3NpdGl2ZSBjb3JyZWxhdGlvbnMgYXJlIHNob3duIGluIHNoYWRlcyBvZiBibHVlLCB3aGlsZSBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMgYXJlIGluIHNoYWRlcyBvZiByZWQuDQoNCktleSBPYnNlcnZhdGlvbnM6DQpDaG9sZXN0ZXJvbDoNCg0KU2hvd3MgYSB3ZWFrIHBvc2l0aXZlIGNvcnJlbGF0aW9uIHdpdGggTWF4SFIgKDAuMjQpLg0KSGFzIGEgd2VhayBuZWdhdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEhlYXJ0RGlzZWFzZSAoLTAuMjMpLCBzdWdnZXN0aW5nIHRoYXQgaGlnaGVyIGNob2xlc3Rlcm9sIGxldmVscyBtYXkgc2xpZ2h0bHkgZGVjcmVhc2UgdGhlIGxpa2VsaWhvb2Qgb2YgaGVhcnQgZGlzZWFzZS4NCk1heEhSOg0KDQpTaG93cyBhIG1vZGVyYXRlIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIHdpdGggSGVhcnREaXNlYXNlICgtMC40MCksIGluZGljYXRpbmcgdGhhdCBoaWdoZXIgbWF4aW11bSBoZWFydCByYXRlcyBhcmUgYXNzb2NpYXRlZCB3aXRoIGEgbG93ZXIgbGlrZWxpaG9vZCBvZiBoZWFydCBkaXNlYXNlLg0KSGFzIGEgd2VhayBuZWdhdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEFnZSAoLTAuMzgpLCBtZWFuaW5nIHRoYXQgb2xkZXIgaW5kaXZpZHVhbHMgdGVuZCB0byBoYXZlIGxvd2VyIG1heGltdW0gaGVhcnQgcmF0ZXMuDQpGYXN0aW5nQlM6DQoNClNob3dzIGEgd2VhayBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEhlYXJ0RGlzZWFzZSAoMC4yNyksIHN1Z2dlc3RpbmcgdGhhdCBoaWdoZXIgZmFzdGluZyBibG9vZCBzdWdhciBsZXZlbHMgc2xpZ2h0bHkgaW5jcmVhc2UgdGhlIGxpa2VsaWhvb2Qgb2YgaGVhcnQgZGlzZWFzZS4NCkhhcyB3ZWFrIHBvc2l0aXZlIGNvcnJlbGF0aW9ucyB3aXRoIG90aGVyIHZhcmlhYmxlcyBsaWtlIEFnZSAoMC4yMCkgYW5kIFJlc3RpbmdCUCAoMC4wNykuDQpSZXN0aW5nQlA6DQoNClNob3dzIGEgd2VhayBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIEhlYXJ0RGlzZWFzZSAoMC4xMSksIGluZGljYXRpbmcgYSBtaW5vciBpbmNyZWFzZSBpbiBoZWFydCBkaXNlYXNlIGxpa2VsaWhvb2Qgd2l0aCBoaWdoZXIgcmVzdGluZyBibG9vZCBwcmVzc3VyZS4NCkhhcyB3ZWFrIHBvc2l0aXZlIGNvcnJlbGF0aW9ucyB3aXRoIEFnZSAoMC4yNSkgYW5kIE9sZHBlYWsgKDAuMTYpLg0KQWdlOg0KDQpTaG93cyBhIHdlYWsgcG9zaXRpdmUgY29ycmVsYXRpb24gd2l0aCBIZWFydERpc2Vhc2UgKDAuMjgpLCBpbmRpY2F0aW5nIHRoYXQgb2xkZXIgYWdlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIGhpZ2hlciBsaWtlbGlob29kIG9mIGhlYXJ0IGRpc2Vhc2UuDQpIYXMgd2VhayB0byBtb2RlcmF0ZSBwb3NpdGl2ZSBjb3JyZWxhdGlvbnMgd2l0aCBvdGhlciB2YXJpYWJsZXMgbGlrZSBSZXN0aW5nQlAgKDAuMjUpLCBPbGRwZWFrICgwLjI2KSwgYW5kIEZhc3RpbmdCUyAoMC4yMCkuDQpPbGRwZWFrOg0KDQpTaG93cyB0aGUgc3Ryb25nZXN0IHBvc2l0aXZlIGNvcnJlbGF0aW9uIHdpdGggSGVhcnREaXNlYXNlICgwLjQwKSBhbW9uZyB0aGUgdmFyaWFibGVzLCBzdWdnZXN0aW5nIHRoYXQgaGlnaGVyIFNUIGRlcHJlc3Npb24gaXMgc3Ryb25nbHkgYXNzb2NpYXRlZCB3aXRoIGEgaGlnaGVyIGxpa2VsaWhvb2Qgb2YgaGVhcnQgZGlzZWFzZS4NCkhhcyB3ZWFrIHBvc2l0aXZlIGNvcnJlbGF0aW9ucyB3aXRoIG90aGVyIHZhcmlhYmxlcyBsaWtlIEFnZSAoMC4yNikgYW5kIFJlc3RpbmdCUCAoMC4xNikuDQpTdW1tYXJ5Og0KTWF4SFIgYW5kIE9sZHBlYWsgYXJlIHRoZSBtb3N0IHNpZ25pZmljYW50IHByZWRpY3RvcnMgb2YgaGVhcnQgZGlzZWFzZSBpbiB0aGlzIGRhdGFzZXQsIHdpdGggTWF4SFIgc2hvd2luZyBhIG1vZGVyYXRlIG5lZ2F0aXZlIGNvcnJlbGF0aW9uIGFuZCBPbGRwZWFrIHNob3dpbmcgYSBtb2RlcmF0ZSBwb3NpdGl2ZSBjb3JyZWxhdGlvbiB3aXRoIGhlYXJ0IGRpc2Vhc2UuDQpBZ2UgYW5kIEZhc3RpbmdCUyBhbHNvIHNob3cgd2VhayBwb3NpdGl2ZSBjb3JyZWxhdGlvbnMgd2l0aCBoZWFydCBkaXNlYXNlLCBpbmRpY2F0aW5nIHRoYXQgb2xkZXIgYWdlIGFuZCBoaWdoZXIgZmFzdGluZyBibG9vZCBzdWdhciBsZXZlbHMgYXJlIGFzc29jaWF0ZWQgd2l0aCBhIHNsaWdodGx5IGhpZ2hlciBsaWtlbGlob29kIG9mIGhlYXJ0IGRpc2Vhc2UuDQpDaG9sZXN0ZXJvbCBhbmQgUmVzdGluZ0JQIHNob3cgd2Vha2VyIGNvcnJlbGF0aW9ucyB3aXRoIGhlYXJ0IGRpc2Vhc2UsIHN1Z2dlc3RpbmcgdGhleSBhcmUgbGVzcyBpbmZsdWVudGlhbCBwcmVkaWN0b3JzIGluIHRoaXMgZGF0YXNldC4NClRoZXNlIGNvcnJlbGF0aW9ucyBwcm92aWRlIGluc2lnaHRzIGludG8gdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBkaWZmZXJlbnQgaGVhbHRoIGluZGljYXRvcnMgYW5kIGhlYXJ0IGRpc2Vhc2UsIGhlbHBpbmcgdG8gaWRlbnRpZnkga2V5IGZhY3RvcnMgdGhhdCBtYXkgY29udHJpYnV0ZSB0byB0aGUgcmlzayBvZiBoZWFydCBkaXNlYXNlLg0KDQojIyMgQ29ycmVsYXRpb24gQW5hbHlzaXMgU3VtbWFyeTogDQojIyMgVGhlIGNvcnJlbGF0aW9uIG1hdHJpeCBoaWdobGlnaHRzIGtleSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdmFyaWFibGVzIHJlbGF0ZWQgdG8gaGVhcnQgZGlzZWFzZS4gTWF4SFIgYW5kIE9sZHBlYWsgYXJlIHRoZSBtb3N0IHNpZ25pZmljYW50IHByZWRpY3RvcnMsIHdpdGggTWF4SFIgbmVnYXRpdmVseSBjb3JyZWxhdGVkICgtMC40MCkgYW5kIE9sZHBlYWsgcG9zaXRpdmVseSBjb3JyZWxhdGVkICgwLjQwKSB3aXRoIGhlYXJ0IGRpc2Vhc2UuIEFnZSBhbmQgRmFzdGluZ0JTIGFsc28gc2hvdyB3ZWFrIHBvc2l0aXZlIGNvcnJlbGF0aW9ucyAoMC4yOCBhbmQgMC4yNywgcmVzcGVjdGl2ZWx5KSB3aXRoIGhlYXJ0IGRpc2Vhc2UsIGluZGljYXRpbmcgb2xkZXIgYWdlIGFuZCBoaWdoZXIgZmFzdGluZyBibG9vZCBzdWdhciBsZXZlbHMgc2xpZ2h0bHkgaW5jcmVhc2UgaGVhcnQgZGlzZWFzZSBsaWtlbGlob29kLiBDaG9sZXN0ZXJvbCBhbmQgUmVzdGluZ0JQIGhhdmUgd2Vha2VyIGNvcnJlbGF0aW9ucyB3aXRoIGhlYXJ0IGRpc2Vhc2UgKC0wLjIzIGFuZCAwLjExLCByZXNwZWN0aXZlbHkpLCBzdWdnZXN0aW5nIHRoZXkgYXJlIGxlc3MgaW5mbHVlbnRpYWwgcHJlZGljdG9ycy4gVGhlc2UgaW5zaWdodHMgaGVscCBpZGVudGlmeSBjcnVjaWFsIGhlYWx0aCBpbmRpY2F0b3JzIGNvbnRyaWJ1dGluZyB0byBoZWFydCBkaXNlYXNlIHJpc2suDQoqKioNCiMgey19DQoNCioqKg0KIyBSZWdyZXNzaW9uIE1vZGVsIHsudGFic2V0fQ0KDQpgYGB7cn0NCiMgTXVsdGlwbGUgTGluZWFyIFJlZ3Jlc3Npb24NCm1vZGVsX2hlYXJ0IDwtIGxtKEhlYXJ0RGlzZWFzZSB+IEFnZSArIFNleCArIFJlc3RpbmdCUCArIENob2xlc3Rlcm9sICsgTWF4SFIgKyANCiAgICAgICAgICAgIEV4ZXJjaXNlQW5naW5hICsgT2xkcGVhayArIFNUX1Nsb3BlLCBkYXRhID0gaGVhcnRfZGF0YSkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShtb2RlbF9oZWFydCkNCmBgYA0KDQojIyBTdW1tYXJ5IG9mIFNvbWV0aGluZyBORVcgdGhhdCB3ZSBoYXZlIG5vdCBjb3ZlcmVkIGluIGNsYXNzLg0KLSBSZWdyZXNzaW9uIG1vZGVsIHN1bW1hcnkgb3VwdXQgYW5kIGludGVycHJldGF0aW9uDQotIENoZWNrIGZvciBtb2RlbCBhc3N1bXB0aW9ucw0KLSBJbnRlcnByZXRhdGlvbiBvZiB0aGUgbW9kZWwgQ29lZmZpY2llbnRzDQoNCg0KIyMgQ2hlY2sgTW9kZWwgQXNzdW1wdGlvbnMgey50YWJzZXR9DQoNCmBgYHtyfQ0KDQoNCiMgQ2hlY2sgbW9kZWwgYXNzdW1wdGlvbnMgKGUuZy4sIHJlc2lkdWFscyBwbG90KQ0KIyBFeHRyYWN0IHJlc2lkdWFscw0KcmVzaWR1YWxzIDwtIHJlc2lkdWFscyhtb2RlbF9oZWFydCkNCg0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHdpdGggdGhlIHJlc2lkdWFscw0KcmVzaWR1YWxzX2RmIDwtIGRhdGEuZnJhbWUocmVzaWR1YWxzID0gcmVzaWR1YWxzKQ0KDQphMSA8LWdncGxvdChyZXNpZHVhbHNfZGYsIGFlcyh4ID0gMTpsZW5ndGgocmVzaWR1YWxzKSwgeSA9IHJlc2lkdWFscykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIikgKw0KICBsYWJzKHRpdGxlID0gIlJlc2lkdWFscyBvZiB0aGUgTW9kZWwiLA0KICAgICAgIHggPSAiSW5kZXgiLA0KICAgICAgIHkgPSAiUmVzaWR1YWxzIikNCg0KYTENCg0KDQojIE5vcm1hbGl0eTogUS1RIHBsb3Qgb2YgcmVzaWR1YWxzDQphMiA8LSBnZ3Bsb3QobW9kZWxfaGVhcnQsIGFlcyhzYW1wbGUgPSAucmVzaWQpKSArDQogIHN0YXRfcXEoKSArDQogIHN0YXRfcXFfbGluZSgpICsNCiAgbGFicyh0aXRsZSA9ICJRLVEgUGxvdCIsIHggPSAiVGhlb3JldGljYWwgUXVhbnRpbGVzIiwgeSA9ICJTYW1wbGUgUXVhbnRpbGVzIikNCmEyDQoNCg0KYGBgDQoNCiMjIyBTdW1tYXJ5IG9mIHRoZSBNb2RlbCBBc3N1bXB0aW9ucw0KDQojIyMgVGhlIHJlc2lkdWFscyBwbG90IHNob3dzIHRoYXQgdGhlIHJlc2lkdWFscyBhcHBlYXIgdG8gYmUgcmFuZG9tbHkgc2NhdHRlcmVkIGFyb3VuZCB0aGUgaG9yaXpvbnRhbCBsaW5lIGF0IHplcm8sIHN1Z2dlc3RpbmcgdGhhdCB0aGUgYXNzdW1wdGlvbiBvZiBob21vc2NlZGFzdGljaXR5IGlzIGxpa2VseSBtZXQsIHRob3VnaCB0aGVyZSBhcmUgYSBmZXcgcG90ZW50aWFsIG91dGxpZXJzIHRoYXQgbWF5IG5lZWQgZnVydGhlciBpbnZlc3RpZ2F0aW9uLiBUaGUgUS1RIHBsb3QgaW5kaWNhdGVzIHRoYXQgdGhlIHJlc2lkdWFscyBhcmUgcm91Z2hseSBub3JtYWxseSBkaXN0cmlidXRlZCwgYXMgdGhlIHBvaW50cyBmYWxsIGFwcHJveGltYXRlbHkgYWxvbmcgdGhlIGRpYWdvbmFsIGxpbmUsIHdpdGggbWlub3IgZGV2aWF0aW9ucyBhdCB0aGUgdGFpbHMgc3VnZ2VzdGluZyBvbmx5IHNsaWdodCBkZXZpYXRpb25zIGZyb20gbm9ybWFsaXR5LiBIb3dldmVyLCB0aGUgQnJldXNjaC1QYWdhbiB0ZXN0IHlpZWxkcyBhIHZlcnkgc21hbGwgcC12YWx1ZSAoOS4zMzVlLTA1KSwgbGVhZGluZyB1cyB0byByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyBvZiBob21vc2NlZGFzdGljaXR5LCBpbmRpY2F0aW5nIGV2aWRlbmNlIG9mIGhldGVyb3NjZWRhc3RpY2l0eSBpbiB0aGUgcmVzaWR1YWxzLiBEZXNwaXRlIHRoZSByZXNpZHVhbHMgcGxvdCB2aXN1YWxseSBzdWdnZXN0aW5nIGNvbnN0YW50IHZhcmlhbmNlLCB0aGUgQnJldXNjaC1QYWdhbiB0ZXN0IGhpZ2hsaWdodHMgcG90ZW50aWFsIGlzc3VlcyB3aXRoIHJlc2lkdWFsIHZhcmlhbmNlIHRoYXQgd2FycmFudCBmdXJ0aGVyIGV4YW1pbmF0aW9uLg0KDQojIyBJbnRlcnByZXRhdGlvbiB7LnRhYnNldH0NClRoZSBtb2RlbCBleHBsYWlucyBhcHByb3hpbWF0ZWx5IDUxLjY2JSAoQWRqdXN0ZWRfUi1zcXVhcmVkKSBvZiB0aGUgdmFyaWFiaWxpdHkgaW4gSGVhcnREaXNlYXNlLg0KU2lnbmlmaWNhbnQgcHJlZGljdG9ycyAod2l0aCBwLXZhbHVlcyA8IDAuMDUpIGluY2x1ZGUgQWdlLCBTZXhNLCBDaG9sZXN0ZXJvbCwgTWF4SFIsIEV4ZXJjaXNlQW5naW5hWSwgT2xkcGVhaywgU1RfU2xvcGVGbGF0LCBhbmQgU1RfU2xvcGVVcC4NClJlc3RpbmdCUCBpcyBub3QgYSBzaWduaWZpY2FudCBwcmVkaWN0b3IgaW4gdGhpcyBtb2RlbC4NClRoZSBvdmVyYWxsIG1vZGVsIGlzIHNpZ25pZmljYW50IChwLXZhbHVlIDwgMi4yZS0xNikuDQpUaGVzZSBpbnNpZ2h0cyBjYW4gaGVscCBpbiB1bmRlcnN0YW5kaW5nIHdoaWNoIGZhY3RvcnMgYXJlIG1vc3Qgc3Ryb25nbHkgYXNzb2NpYXRlZCB3aXRoIGhlYXJ0IGRpc2Vhc2UgYWNjb3JkaW5nIHRvIHRoZSBtb2RlbC4NCg0KUmVzaWR1YWxzDQpUaGUgcmVzaWR1YWxzIGFyZSB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgb2JzZXJ2ZWQgYW5kIHByZWRpY3RlZCB2YWx1ZXMgb2YgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSAoSGVhcnREaXNlYXNlKS4gVGhlIHN1bW1hcnkgc3RhdGlzdGljcyBvZiB0aGUgcmVzaWR1YWxzIGdpdmUgdXMgYW4gaWRlYSBvZiB0aGUgZGlzdHJpYnV0aW9uOg0KDQpNaW46IC0xLjA5NDcNCjFRIChGaXJzdCBRdWFydGlsZSk6IC0wLjE3NzANCk1lZGlhbjogMC4wMDg1DQozUSAoVGhpcmQgUXVhcnRpbGUpOiAwLjE4MjANCk1heDogMS4wNTkyDQpUaGUgbWVkaWFuIHJlc2lkdWFsIGlzIGNsb3NlIHRvIHplcm8sIHN1Z2dlc3RpbmcgdGhhdCB0aGUgbW9kZWwgZG9lcyBub3QgaGF2ZSBhIGxhcmdlIHN5c3RlbWF0aWMgYmlhcy4gVGhlIHJhbmdlIChmcm9tIC0xLjA5NDcgdG8gMS4wNTkyKSBpbmRpY2F0ZXMgaG93IGZhciB0aGUgcmVzaWR1YWxzIHR5cGljYWxseSBkZXZpYXRlIGZyb20gemVyby4NCg0KDQpDb2VmZmljaWVudHMNClRoZSBjb2VmZmljaWVudHMgdGFibGUgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVhY2ggcHJlZGljdG9yIGFuZCB0aGUgb3V0Y29tZSB2YXJpYWJsZSwgY29udHJvbGxpbmcgZm9yIHRoZSBvdGhlciBwcmVkaWN0b3JzLg0KDQpJbnRlcmNlcHQgKDAuNDI4Nzk1Myk6IFRoZSBleHBlY3RlZCB2YWx1ZSBvZiBIZWFydERpc2Vhc2Ugd2hlbiBhbGwgcHJlZGljdG9ycyBhcmUgemVyby4gSG93ZXZlciwgdGhpcyBtaWdodCBub3QgYmUgbWVhbmluZ2Z1bCBpZiB6ZXJvIGlzIG5vdCBhIHJlYWxpc3RpYyB2YWx1ZSBmb3IgdGhlIHByZWRpY3RvcnMuDQoNCkFnZSAoMC4wMDMyMTc0LCBwID0gMC4wMTk4MCk6IEZvciBlYWNoIGFkZGl0aW9uYWwgeWVhciBvZiBhZ2UsIHRoZSBleHBlY3RlZCBpbmNyZWFzZSBpbiBIZWFydERpc2Vhc2UgaXMgMC4wMDMyIHVuaXRzLCBob2xkaW5nIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudC4gVGhpcyBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wNSksIGluZGljYXRpbmcgYWdlIGlzIGEgbWVhbmluZ2Z1bCBwcmVkaWN0b3IuDQoNClNleE0gKDAuMTg1NTg4NywgcCA9IDMuNjhlLTEwKTogQmVpbmcgbWFsZSBpbmNyZWFzZXMgdGhlIGV4cGVjdGVkIHZhbHVlIG9mIEhlYXJ0RGlzZWFzZSBieSAwLjE4NTYgdW5pdHMgY29tcGFyZWQgdG8gZmVtYWxlcywgaG9sZGluZyBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQuIFRoaXMgaXMgaGlnaGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLg0KDQpSZXN0aW5nQlAgKDAuMDAwMjA0NCwgcCA9IDAuNzUzMjkpOiBSZXN0aW5nIGJsb29kIHByZXNzdXJlIGRvZXMgbm90IGhhdmUgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGVmZmVjdCBvbiBIZWFydERpc2Vhc2UgaW4gdGhpcyBtb2RlbCAocCA+IDAuMSkuDQoNCkNob2xlc3Rlcm9sICgtMC4wMDA2NzUzLCBwID0gMS43NWUtMDkpOiBFYWNoIHVuaXQgaW5jcmVhc2UgaW4gY2hvbGVzdGVyb2wgbGV2ZWwgZGVjcmVhc2VzIHRoZSBsaWtlbGlob29kIG9mIGhhdmluZyAgSGVhcnREaXNlYXNlIGJ5IDAuMDAwNjc1MyB1bml0cywgd2hpY2ggaXMgaGlnaGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLiBUaGlzIG5lZ2F0aXZlIHJlbGF0aW9uc2hpcCBtaWdodCBuZWVkIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbi4NCg0KTWF4SFIgKC0wLjAwMTMxODQsIHAgPSAwLjAxNTMwKTogRWFjaCB1bml0IGluY3JlYXNlIGluIG1heGltdW0gaGVhcnQgcmF0ZSBhY2hpZXZlZCBkZWNyZWFzZXMgdGhlIGV4cGVjdGVkIHZhbHVlIG9mIEhlYXJ0RGlzZWFzZSBieSAwLjAwMTMxODQgdW5pdHMsIGFuZCB0aGlzIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAgPCAwLjA1KS4NCg0KRXhlcmNpc2VBbmdpbmFZICgwLjE5MTY1MTksIHAgPSAxLjkyZS0xMSk6IFByZXNlbmNlIG9mIGV4ZXJjaXNlLWluZHVjZWQgYW5naW5hIGluY3JlYXNlcyB0aGUgZXhwZWN0ZWQgdmFsdWUgb2YgSGVhcnREaXNlYXNlIGJ5IDAuMTkxNjUxOSB1bml0cywgaGlnaGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLg0KDQpPbGRwZWFrICgwLjA1OTI3NzYsIHAgPSA3LjM0ZS0wNik6IEVhY2ggdW5pdCBpbmNyZWFzZSBpbiBTVCBkZXByZXNzaW9uIGluZHVjZWQgYnkgZXhlcmNpc2UgcmVsYXRpdmUgdG8gcmVzdCBpbmNyZWFzZXMgSGVhcnREaXNlYXNlIGJ5IDAuMDU5Mjc3NiB1bml0cywgaGlnaGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLg0KDQpTVF9TbG9wZUZsYXQgKDAuMTU0NTI2NCwgcCA9IDAuMDAxNDYpOiBIYXZpbmcgYSBmbGF0IHNsb3BlIG9mIHRoZSBwZWFrIGV4ZXJjaXNlIFNUIHNlZ21lbnQgaW5jcmVhc2VzIEhlYXJ0RGlzZWFzZSBieSAwLjE1NDUyNjQgdW5pdHMsIHNpZ25pZmljYW50IChwIDwgMC4wMSkuDQpTVF9TbG9wZVVwICgtMC4yNjUxMzk0LCBwID0gOS40NmUtMDcpOiBIYXZpbmcgYW4gdXBzbG9waW5nIFNUIHNlZ21lbnQgZGVjcmVhc2VzIEhlYXJ0RGlzZWFzZSBieSAwLjI2NTEzOTQgdW5pdHMsIGhpZ2hseSBzaWduaWZpY2FudCAocCA8IDAuMDAxKS4NCg0KU3VtbWFyeSBvZiBSZWdyZXNzaW9uIE1vZGVsIEludGVycHJldGF0aW9uDQpNb2RlbCBFeHBsYW5hdGlvbjoNCg0KVGhlIG1vZGVsIGV4cGxhaW5zIGFwcHJveGltYXRlbHkgNTEuNjYlIG9mIHRoZSB2YXJpYWJpbGl0eSBpbiBoZWFydCBkaXNlYXNlIG91dGNvbWVzLCBhcyBpbmRpY2F0ZWQgYnkgdGhlIEFkanVzdGVkIFItc3F1YXJlZCB2YWx1ZS4NCg0KU2lnbmlmaWNhbnQgUHJlZGljdG9yczoNCg0KVGhlIGZvbGxvd2luZyBwcmVkaWN0b3JzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwLXZhbHVlcyA8IDAuMDUpLCBpbmRpY2F0aW5nIGEgbWVhbmluZ2Z1bCByZWxhdGlvbnNoaXAgd2l0aCBoZWFydCBkaXNlYXNlOg0KDQpBZ2U6IE9sZGVyIGFnZSBpcyBhc3NvY2lhdGVkIHdpdGggYW4gaW5jcmVhc2VkIGxpa2VsaWhvb2Qgb2YgaGVhcnQgZGlzZWFzZS4NCg0KU2V4IChNYWxlKTogTWFsZXMgaGF2ZSBhIGhpZ2hlciBsaWtlbGlob29kIG9mIGhlYXJ0IGRpc2Vhc2UgY29tcGFyZWQgdG8gZmVtYWxlcy4NCg0KQ2hvbGVzdGVyb2w6IEhpZ2hlciBjaG9sZXN0ZXJvbCBsZXZlbHMgYXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGhlYXJ0IGRpc2Vhc2UuDQoNCk1heEhSIChNYXhpbXVtIEhlYXJ0IFJhdGUgQWNoaWV2ZWQpOiBMb3dlciBtYXhpbXVtIGhlYXJ0IHJhdGUgYWNoaWV2ZWQgaXMgYXNzb2NpYXRlZCB3aXRoIGFuIGluY3JlYXNlZCBsaWtlbGlob29kIG9mIGhlYXJ0IGRpc2Vhc2UuDQoNCkV4ZXJjaXNlLUluZHVjZWQgQW5naW5hIChFeGVyY2lzZUFuZ2luYVkpOiBQcmVzZW5jZSBvZiBleGVyY2lzZS1pbmR1Y2VkIGFuZ2luYSBpcyBhc3NvY2lhdGVkIHdpdGggYSBoaWdoZXIgbGlrZWxpaG9vZCBvZiBoZWFydCBkaXNlYXNlLg0KDQpPbGRwZWFrOiBIaWdoZXIgU1QgZGVwcmVzc2lvbiBpbmR1Y2VkIGJ5IGV4ZXJjaXNlIHJlbGF0aXZlIHRvIHJlc3QgaXMgYXNzb2NpYXRlZCB3aXRoIGhlYXJ0IGRpc2Vhc2UuDQoNClNUIFNsb3BlIChGbGF0IGFuZCBVcCk6IEZsYXQgU1Qgc2xvcGUgaXMgYXNzb2NpYXRlZCB3aXRoIGEgaGlnaGVyIGxpa2VsaWhvb2QsIHdoaWxlIHVwc2xvcGluZyBTVCBzZWdtZW50IGlzIGFzc29jaWF0ZWQgd2l0aCBhIGxvd2VyIGxpa2VsaWhvb2Qgb2YgaGVhcnQgZGlzZWFzZS4NCg0KTm9uLVNpZ25pZmljYW50IFByZWRpY3RvcjoNCg0KUmVzdGluZyBCbG9vZCBQcmVzc3VyZSAoUmVzdGluZ0JQKTogVGhpcyBwcmVkaWN0b3IgZG9lcyBub3QgaGF2ZSBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZWZmZWN0IG9uIGhlYXJ0IGRpc2Vhc2UgaW4gdGhpcyBtb2RlbC4NCg0KT3ZlcmFsbCBNb2RlbCBTaWduaWZpY2FuY2U6DQoNClRoZSBtb2RlbCBhcyBhIHdob2xlIGlzIGhpZ2hseSBzaWduaWZpY2FudCwgd2l0aCBhIHAtdmFsdWUgbGVzcyB0aGFuIDIuMmUtMTYsIGluZGljYXRpbmcgdGhhdCB0aGUgcHJlZGljdG9ycywgd2hlbiBjb25zaWRlcmVkIHRvZ2V0aGVyLCByZWxpYWJseSBwcmVkaWN0IGhlYXJ0IGRpc2Vhc2UuDQoNCkNvbmNsdXNpb246DQoNClRoaXMgbW9kZWwgcHJvdmlkZXMgdmFsdWFibGUgaW5zaWdodHMgaW50byB0aGUgZmFjdG9ycyBtb3N0IHN0cm9uZ2x5IGFzc29jaWF0ZWQgd2l0aCBoZWFydCBkaXNlYXNlLCB3aGljaCBjYW4gYmUgY3JpdGljYWwgZm9yIHVuZGVyc3RhbmRpbmcgcmlzayBhbmQgaW5mb3JtaW5nIHByZXZlbnRhdGl2ZSBtZWFzdXJlcy4gVGhlIHNpZ25pZmljYW50IHByZWRpY3RvcnMgaGlnaGxpZ2h0IGtleSBhcmVhcyBmb3IgbW9uaXRvcmluZyBhbmQgaW50ZXJ2ZW50aW9uIGluIGNsaW5pY2FsIHByYWN0aWNlLg0KDQoNCiMjIFBlcmZvcm0gdGhlIEJyZXVzY2gtUGFnYW4gdGVzdCBmb3IgaG9tb3NjZWRhc3RpY2l0eSB7LnRhYnNldH0NCg0KYGBge3J9DQphMyA8LSBicHRlc3QobW9kZWxfaGVhcnQpDQphMw0KYGBgDQoNCiMjIyBJbnRlcnByZXRhdGlvbiBvZiBSZWdyZXNzaW9uIFN1bW1hcnkgT3V0cHV0DQoNClRoZSByZWdyZXNzaW9uIG1vZGVsIGV4cGxhaW5zIDUxLjY2JSBvZiBoZWFydCBkaXNlYXNlIHZhcmlhYmlsaXR5IChBZGp1c3RlZF9SLXNxdWFyZWQgPSAwLjUxNjYpLCBoaWdobGlnaHRpbmcgc2lnbmlmaWNhbnQgcHJlZGljdG9yczogQWdlLCBTZXhNLCBDaG9sZXN0ZXJvbCwgTWF4SFIsIEV4ZXJjaXNlQW5naW5hWSwgT2xkcGVhaywgU1RfU2xvcGVGbGF0LCBhbmQgU1RfU2xvcGVVcC4gQWdlIGJldHdlZW4gNTEgdG8gNjYgYW5kIGJlaW5nIG1hbGUgaW5jcmVhc2UgaGVhcnQgZGlzZWFzZSByaXNrLCB3aGlsZSBoaWdoZXIgY2hvbGVzdGVyb2wgc2xpZ2h0bHkgZGVjcmVhc2VzIGl0LiBMb3dlciBNYXhIUiBhbmQgcHJlc2VuY2Ugb2YgZXhlcmNpc2UtaW5kdWNlZCBhbmdpbmEgcmFpc2UgaGVhcnQgZGlzZWFzZSBsaWtlbGlob29kLiBIaWdoZXIgT2xkcGVhayAoU1QgZGVwcmVzc2lvbikgYW5kIGEgZmxhdCBTVCBzbG9wZSBpbmNyZWFzZSByaXNrLCB3aGlsZSBhbiB1cHNsb3BpbmcgU1Qgc2VnbWVudCBkZWNyZWFzZXMgaXQuIFJlc3RpbmdCUCBpcyBub3Qgc2lnbmlmaWNhbnQuIFRoZSBtb2RlbCBpcyBoaWdobHkgcmVsaWFibGUgKHAtdmFsdWUgPCAyLjJlLTE2KSwgYWlkaW5nIGluIGVmZmVjdGl2ZSBoZWFydCBkaXNlYXNlIHJpc2sgYXNzZXNzbWVudCBhbmQgbWFuYWdlbWVudC4NCioqKg0KIyB7LX0NCg0KKioqDQojIENvbmNsdXNpb24gey50YWJzZXR9DQojIyBUaGlzIG1vZGVsIHByb3ZpZGVzIHZhbHVhYmxlIGluc2lnaHRzIGludG8gdGhlIGZhY3RvcnMgbW9zdCBzdHJvbmdseSBhc3NvY2lhdGVkIHdpdGggaGVhcnQgZGlzZWFzZSwgd2hpY2ggY2FuIGJlIGNyaXRpY2FsIGZvciB1bmRlcnN0YW5kaW5nIHJpc2sgYW5kIGluZm9ybWluZyBwcmV2ZW50YXRpdmUgbWVhc3VyZXMuIFRoZSBzaWduaWZpY2FudCBwcmVkaWN0b3JzIGhpZ2hsaWdodCBrZXkgYXJlYXMgZm9yIG1vbml0b3JpbmcgYW5kIGludGVydmVudGlvbiBpbiBjbGluaWNhbCBwcmFjdGljZS4NCg0KKioqDQojIFdlYnNpdGUNCg0KPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+DQogIDxpbWcgc3JjPSJodHRwczovL3d3dy5hbWVyaWNhbi5lZHUvdWNtL2ltYWdlcy9BVV9sb2dvX3ByaW1hcnkucG5nIiBhbHQ9IkNlbnRlcmVkIEltYWdlIiBzdHlsZT0id2lkdGg6NTAlOyI+DQo8L2Rpdj4NCg0KPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+DQogIDxhIGhyZWY9Imh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvZmVkZXNvcmlhbm8vaGVhcnQtZmFpbHVyZS1wcmVkaWN0aW9uIiB0YXJnZXQ9Il9ibGFuayI+RGF0YSBVUkwgPC9hPg0KPC9kaXY+DQoNCioqKg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg==